aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2017-07-31 15:13:15 -0400
committerJack Lloyd <[email protected]>2017-08-25 17:36:51 -0400
commit3baa546d70bcd078b23be07069d755a5f130fb0f (patch)
treed626d73fdf845987e2d1783e8493593501378a07
parent41e1e7cbc1e4e864ad5d15dd0c09227b04940a91 (diff)
Create new fuzzer build mode
-rw-r--r--.travis.yml12
-rwxr-xr-xconfigure.py109
-rw-r--r--src/build-data/buildh.in1
-rw-r--r--src/build-data/makefile/gmake.in2
-rw-r--r--src/build-data/makefile/gmake_fuzzers.in18
-rw-r--r--src/extra_tests/fuzzers/.gitignore10
-rw-r--r--src/extra_tests/fuzzers/GNUmakefile88
-rw-r--r--src/extra_tests/fuzzers/readme.txt49
-rw-r--r--src/fuzzer/asn1.cpp (renamed from src/extra_tests/fuzzers/jigs/ber_decode.cpp)13
-rw-r--r--src/fuzzer/bn_sqr.cpp (renamed from src/extra_tests/fuzzers/jigs/bn_sqr.cpp)2
-rw-r--r--src/fuzzer/cert.cpp (renamed from src/extra_tests/fuzzers/jigs/cert.cpp)8
-rw-r--r--src/fuzzer/crl.cpp (renamed from src/extra_tests/fuzzers/jigs/crl.cpp)11
-rw-r--r--src/fuzzer/divide.cpp (renamed from src/extra_tests/fuzzers/jigs/divide.cpp)10
-rw-r--r--src/fuzzer/ecc_bp256.cpp (renamed from src/extra_tests/fuzzers/jigs/ecc_bp256.cpp)4
-rw-r--r--src/fuzzer/ecc_helper.h (renamed from src/extra_tests/fuzzers/jigs/ecc_helper.h)29
-rw-r--r--src/fuzzer/ecc_p256.cpp (renamed from src/extra_tests/fuzzers/jigs/ecc_p256.cpp)4
-rw-r--r--src/fuzzer/ecc_p384.cpp (renamed from src/extra_tests/fuzzers/jigs/ecc_p384.cpp)4
-rw-r--r--src/fuzzer/ecc_p521.cpp (renamed from src/extra_tests/fuzzers/jigs/ecc_p521.cpp)4
-rw-r--r--src/fuzzer/fuzzers.h (renamed from src/extra_tests/fuzzers/jigs/driver.h)104
-rw-r--r--src/fuzzer/invert.cpp (renamed from src/extra_tests/fuzzers/jigs/invert.cpp)21
-rw-r--r--src/fuzzer/ocsp.cpp (renamed from src/extra_tests/fuzzers/jigs/ocsp.cpp)4
-rw-r--r--src/fuzzer/os2ecp.cpp (renamed from src/extra_tests/fuzzers/jigs/os2ecp.cpp)24
-rw-r--r--src/fuzzer/pkcs1.cpp (renamed from src/extra_tests/fuzzers/jigs/pkcs1.cpp)25
-rw-r--r--src/fuzzer/pkcs8.cpp (renamed from src/extra_tests/fuzzers/jigs/pkcs8.cpp)7
-rw-r--r--src/fuzzer/pow_mod.cpp (renamed from src/extra_tests/fuzzers/jigs/pow_mod.cpp)25
-rw-r--r--src/fuzzer/redc_helper.h33
-rw-r--r--src/fuzzer/redc_p192.cpp (renamed from src/extra_tests/fuzzers/jigs/redc_p192.cpp)8
-rw-r--r--src/fuzzer/redc_p224.cpp (renamed from src/extra_tests/fuzzers/jigs/redc_p224.cpp)8
-rw-r--r--src/fuzzer/redc_p256.cpp (renamed from src/extra_tests/fuzzers/jigs/redc_p256.cpp)8
-rw-r--r--src/fuzzer/redc_p384.cpp (renamed from src/extra_tests/fuzzers/jigs/redc_p384.cpp)8
-rw-r--r--src/fuzzer/redc_p521.cpp (renamed from src/extra_tests/fuzzers/jigs/redc_p521.cpp)8
-rw-r--r--src/fuzzer/ressol.cpp (renamed from src/extra_tests/fuzzers/jigs/ressol.cpp)14
-rw-r--r--src/fuzzer/tls_client.cpp (renamed from src/extra_tests/fuzzers/jigs/tls_client.cpp)24
-rw-r--r--src/fuzzer/tls_client_hello.cpp (renamed from src/extra_tests/fuzzers/jigs/tls_client_hello.cpp)3
-rw-r--r--src/fuzzer/tls_server.cpp (renamed from src/extra_tests/fuzzers/jigs/tls_server.cpp)32
-rwxr-xr-xsrc/scripts/ci/travis/build.sh13
-rwxr-xr-xsrc/scripts/create_corpus_zip.py48
-rwxr-xr-xsrc/scripts/test_fuzzers.py78
38 files changed, 475 insertions, 398 deletions
diff --git a/.travis.yml b/.travis.yml
index d7092f01a..8431729b4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -31,6 +31,7 @@ env:
- BUILD_MODE="static"
- BUILD_MODE="bsi"
- BUILD_MODE="nist"
+ - BUILD_MODE="fuzzers"
- BUILD_MODE="sanitizer"
- BUILD_MODE="coverage"
- BUILD_MODE="cross-arm32"
@@ -52,10 +53,11 @@ matrix:
- os: osx
compiler: gcc
- # Run docs, lint, bsi, nist, coverage, valgrind, sonarqube, sanitizer,
- # minimized and non-ARM cross builds on Linux/gcc only. The
- # sanitizer builds under Clang run the tests very slowly and cause
- # CI timeouts.
+ # Run docs, lint, bsi, nist, fuzzers, coverage, valgrind, sonarqube, sanitizer,
+ # minimized and non-ARM cross builds on Linux/gcc only.
+
+ # The sanitizer builds under Clang run the tests very slowly and
+ # cause CI timeouts.
- compiler: clang
env: BUILD_MODE="bsi"
@@ -72,6 +74,8 @@ matrix:
- compiler: clang
env: BUILD_MODE="sanitizer"
- compiler: clang
+ env: BUILD_MODE="fuzzers"
+ - compiler: clang
env: BUILD_MODE="valgrind"
- compiler: clang
env: BUILD_MODE="mini-shared"
diff --git a/configure.py b/configure.py
index 58a4f19d2..f9bf90fc9 100755
--- a/configure.py
+++ b/configure.py
@@ -183,6 +183,13 @@ class BuildPaths(object): # pylint: disable=too-many-instance-attributes
self.cli_headers = list(find_headers_in(source_paths.src_dir, 'cli'))
self.test_sources = list(find_sources_in(source_paths.src_dir, 'tests'))
+ if options.build_fuzzers:
+ self.fuzzer_sources = list(find_sources_in(source_paths.src_dir, 'fuzzer'))
+ self.fuzzer_output_dir = os.path.join(self.build_dir, 'fuzzer')
+ else:
+ self.fuzzer_sources = None
+ self.fuzzer_output_dir = None
+
def build_dirs(self):
out = [
self.libobj_dir,
@@ -195,6 +202,8 @@ class BuildPaths(object): # pylint: disable=too-many-instance-attributes
]
if self.doc_output_dir_doxygen:
out += [self.doc_output_dir_doxygen]
+ if self.fuzzer_output_dir:
+ out += [self.fuzzer_output_dir]
return out
def src_info(self, typ):
@@ -204,6 +213,10 @@ class BuildPaths(object): # pylint: disable=too-many-instance-attributes
return (self.cli_sources, self.cliobj_dir)
elif typ == 'test':
return (self.test_sources, self.testobj_dir)
+ elif typ == 'fuzzer':
+ return (self.fuzzer_sources, self.fuzzer_output_dir)
+ else:
+ raise InternalError("Unknown src info type '%s'" % (typ))
PKG_CONFIG_FILENAME = 'botan-%d.pc' % (Version.major)
@@ -409,7 +422,14 @@ def process_command_line(args): # pylint: disable=too-many-locals
help='Generate CMakeLists.txt which can be used to create many IDEs project files')
build_group.add_option('--unsafe-fuzzer-mode', action='store_true', default=False,
- help='disable essential checks for testing')
+ help='Disable essential checks for testing')
+
+ build_group.add_option('--build-fuzzers=', dest='build_fuzzers',
+ metavar='TYPE', default=None,
+ help='Build fuzzers (afl, libfuzzer, test)')
+
+ build_group.add_option('--with-fuzzer-lib=', metavar='LIB', default=None, dest='fuzzer_lib',
+ help='additionally link in LIB')
mods_group = optparse.OptionGroup(parser, 'Module selection')
@@ -1711,13 +1731,14 @@ class MakefileListsGenerator(object):
for src in sources:
(directory, filename) = os.path.split(os.path.normpath(src))
+ obj_suffix = '.' + self._osinfo.obj_suffix
+
parts = directory.split(os.sep)
+ if 'fuzzer' in parts:
+ obj_suffix = ''
+
if 'src' in parts:
parts = parts[parts.index('src')+2:]
- elif 'tests' in parts:
- parts = parts[parts.index('tests')+2:]
- elif 'cli' in parts:
- parts = parts[parts.index('cli'):]
elif filename.find('botan_all') != -1:
parts = []
else:
@@ -1744,8 +1765,7 @@ class MakefileListsGenerator(object):
else:
name = filename
- for src_suffix in ['.cpp', '.S']:
- name = name.replace(src_suffix, '.' + self._osinfo.obj_suffix)
+ name = name.replace('.cpp', obj_suffix)
yield os.path.join(obj_dir, name)
@@ -1760,21 +1780,29 @@ class MakefileListsGenerator(object):
if self._options.with_external_includedir:
includes += ' ' + self._cc.add_include_dir_option + self._options.with_external_includedir
- for (obj_file, src) in zip(self._objectfile_list(sources, obj_dir), sources):
- isa_specific_flags_str = "".join([" %s" % flagset for flagset in sorted(self._isa_specific_flags(src))])
- yield '%s: %s\n\t$(CXX)%s $(%s_FLAGS) %s %s %s %s$@\n' % (
- obj_file,
- src,
- isa_specific_flags_str,
- flags,
- includes,
- self._cc.compile_flags,
- src,
- self._cc.output_to_option)
+ is_fuzzer = obj_dir.find('fuzzer') != -1
+
+ if is_fuzzer:
+ for (obj_file, src) in zip(self._objectfile_list(sources, obj_dir), sources):
+
+ yield '%s: %s\n\t$(CXX) %s $(%s_FLAGS) %s -L. -lbotan-2 $(FUZZER_LINKS_TO) %s$@\n' % (
+ obj_file, src, includes, flags, src, self._cc.output_to_option)
+ else:
+ for (obj_file, src) in zip(self._objectfile_list(sources, obj_dir), sources):
+ isa_specific_flags_str = "".join([" %s" % flagset for flagset in sorted(self._isa_specific_flags(src))])
+
+ yield '%s: %s\n\t$(CXX)%s $(%s_FLAGS) %s %s %s %s$@\n' % (
+ obj_file, src, isa_specific_flags_str, flags,
+ includes, self._cc.compile_flags, src, self._cc.output_to_option)
def generate(self):
out = {}
- for t in ['lib', 'cli', 'test']:
+
+ targets = ['lib', 'cli', 'test']
+ if self._options.build_fuzzers:
+ targets += ['fuzzer']
+
+ for t in targets:
obj_key = '%s_objs' % (t)
src_list, src_dir = self._build_paths.src_info(t)
src_list.sort()
@@ -1817,7 +1845,7 @@ class HouseEccCurve(object):
return "\\\n" + ' \\\n'.join(lines)
-def create_template_vars(source_paths, build_config, options, modules, cc, arch, osinfo):
+def create_template_vars(source_paths, build_config, options, modules, cc, arch, osinfo): #pylint: disable=too-many-locals,too-many-branches
"""
Create the template variables needed to process the makefile, build.h, etc
"""
@@ -1846,6 +1874,7 @@ def create_template_vars(source_paths, build_config, options, modules, cc, arch,
exceptions = match.group(1).split(',')
if osinfo.basename not in exceptions:
libs |= set(module_link_to)
+
return sorted(libs)
def choose_mp_bits():
@@ -1909,6 +1938,7 @@ def create_template_vars(source_paths, build_config, options, modules, cc, arch,
'libobj_dir': build_config.libobj_dir,
'cliobj_dir': build_config.cliobj_dir,
'testobj_dir': build_config.testobj_dir,
+ 'fuzzobj_dir': build_config.fuzzer_output_dir if build_config.fuzzer_output_dir else '',
'doc_output_dir': build_config.doc_output_dir,
@@ -1938,6 +1968,7 @@ def create_template_vars(source_paths, build_config, options, modules, cc, arch,
'lib_link_cmd': cc.so_link_command_for(osinfo.basename, options) + external_link_cmd(),
'cli_link_cmd': cc.binary_link_command_for(osinfo.basename, options) + external_link_cmd(),
'test_link_cmd': cc.binary_link_command_for(osinfo.basename, options) + external_link_cmd(),
+ 'fuzzer_link_cmd': cc.binary_link_command_for(osinfo.basename, options) + external_link_cmd(),
'link_to': ' '.join(
[cc.add_lib_option + lib for lib in link_to('libs')] +
@@ -1956,7 +1987,9 @@ def create_template_vars(source_paths, build_config, options, modules, cc, arch,
'include_files': makefile_list(build_config.public_headers),
- 'unsafe_fuzzer_mode_define': '' if not options.unsafe_fuzzer_mode else '#define BOTAN_UNSAFE_FUZZER_MODE',
+ 'unsafe_fuzzer_mode_define': '#define BOTAN_UNSAFE_FUZZER_MODE' if options.unsafe_fuzzer_mode else '',
+ 'fuzzer_type': '#define BOTAN_FUZZER_IS_%s' % (options.build_fuzzers.upper()) if options.build_fuzzers else '',
+ 'fuzzer_libs': '' if options.fuzzer_lib is None else '%s%s' % (cc.add_lib_option, options.fuzzer_lib),
'ar_command': cc.ar_command or osinfo.ar_command,
'ranlib_command': osinfo.ranlib_command(),
@@ -2026,17 +2059,22 @@ def create_template_vars(source_paths, build_config, options, modules, cc, arch,
variables["header_in"] = process_template(os.path.join(source_paths.makefile_dir, 'header.in'), variables)
if variables["makefile_style"] == "gmake":
- variables["gmake_commands_in"] = process_template(
- os.path.join(source_paths.makefile_dir, 'gmake_commands.in'),
- variables)
- variables["gmake_dso_in"] = process_template(
- os.path.join(source_paths.makefile_dir, 'gmake_dso.in'),
- variables
- ) if options.build_shared_lib else ''
- variables["gmake_coverage_in"] = process_template(
- os.path.join(source_paths.makefile_dir, 'gmake_coverage.in'),
- variables
- ) if options.with_coverage_info else ''
+ templates = [
+ ('gmake_commands.in', True),
+ ('gmake_dso.in', options.build_shared_lib),
+ ('gmake_coverage.in', options.with_coverage_info),
+ ('gmake_fuzzers.in', options.build_fuzzers)
+ ]
+
+ for (template, build_it) in templates:
+ template_file = os.path.join(source_paths.makefile_dir, template)
+
+ var_name = template.replace('.', '_')
+
+ if build_it:
+ variables[var_name] = process_template(template_file, variables)
+ else:
+ variables[var_name] = ''
return variables
@@ -3006,6 +3044,13 @@ def main(argv):
source_paths = SourcePaths(os.path.dirname(argv[0]))
+ if options.build_fuzzers != None:
+ if options.build_fuzzers not in ['libfuzzer', 'afl', 'test']:
+ raise UserError('Bad value to --build-fuzzers')
+
+ if options.build_fuzzers == 'libfuzzer' and options.fuzzer_lib is None:
+ options.fuzzer_lib = 'Fuzzer'
+
info_modules = load_info_files(source_paths.lib_dir, 'Modules', "info.txt", ModuleInfo)
info_arch = load_build_data_info_files(source_paths, 'CPU info', 'arch', ArchInfo)
info_os = load_build_data_info_files(source_paths, 'OS info', 'os', OsInfo)
diff --git a/src/build-data/buildh.in b/src/build-data/buildh.in
index 2376b056e..6e60718ee 100644
--- a/src/build-data/buildh.in
+++ b/src/build-data/buildh.in
@@ -25,6 +25,7 @@
/* How many bits per limb in a BigInt */
#define BOTAN_MP_WORD_BITS %{mp_bits}
%{unsafe_fuzzer_mode_define}
+%{fuzzer_type}
#define BOTAN_INSTALL_PREFIX R"(%{prefix})"
#define BOTAN_INSTALL_HEADER_DIR "%{includedir}/botan-%{version_major}"
diff --git a/src/build-data/makefile/gmake.in b/src/build-data/makefile/gmake.in
index 22e4ef778..c77c1908c 100644
--- a/src/build-data/makefile/gmake.in
+++ b/src/build-data/makefile/gmake.in
@@ -53,6 +53,8 @@ $(STATIC_LIB): $(LIBOBJS)
%{gmake_coverage_in}
+%{gmake_fuzzers_in}
+
SPHINX_CONFIG = %{sphinx_config_dir}
SPHINX_OPTS = -b html
diff --git a/src/build-data/makefile/gmake_fuzzers.in b/src/build-data/makefile/gmake_fuzzers.in
new file mode 100644
index 000000000..82fa8b256
--- /dev/null
+++ b/src/build-data/makefile/gmake_fuzzers.in
@@ -0,0 +1,18 @@
+
+# Fuzzer build commands
+
+FUZZER_LINK_CMD = %{fuzzer_link_cmd}
+FUZZER_LINKS_TO = $(LIB_LINKS_TO) %{fuzzer_libs}
+FUZZER_FLAGS = $(CXXFLAGS) $(WARN_FLAGS)
+
+%{fuzzer_build_cmds}
+
+FUZZERS=%{fuzzer_objs}
+
+fuzzers: libs $(FUZZERS)
+
+fuzzer_corpus:
+ git clone --depth=1 https://github.com/randombit/crypto-corpus.git fuzzer_corpus
+
+fuzzer_corpus_zip: fuzzer_corpus
+ ./src/scripts/create_corpus_zip.py fuzzer_corpus %{fuzzobj_dir}
diff --git a/src/extra_tests/fuzzers/.gitignore b/src/extra_tests/fuzzers/.gitignore
deleted file mode 100644
index f7ce206a2..000000000
--- a/src/extra_tests/fuzzers/.gitignore
+++ /dev/null
@@ -1,10 +0,0 @@
-*.log
-
-/libFuzzer
-libFuzzer.a
-
-/output
-/botan
-/bin
-callgrind.out.*
-/corpus/
diff --git a/src/extra_tests/fuzzers/GNUmakefile b/src/extra_tests/fuzzers/GNUmakefile
deleted file mode 100644
index 32b353d17..000000000
--- a/src/extra_tests/fuzzers/GNUmakefile
+++ /dev/null
@@ -1,88 +0,0 @@
-
-FUZZERS=$(patsubst jigs/%.cpp,%,$(wildcard jigs/*.cpp))
-
-AFL_SAN_FLAGS=-fsanitize=address,undefined -fno-sanitize-recover=undefined
-CLANG_SAN_FLAGS=-fsanitize=address,undefined -fno-sanitize-recover=undefined
-#CLANG_SAN_FLAGS=-fsanitize=address
-
-CLANG_COV_FLAGS=-fsanitize-coverage=edge,indirect-calls,8bit-counters
-SHARED_FLAGS=-O3 -g -std=c++11 -pthread
-CFG_FLAGS=--with-debug-info --unsafe-fuzzer-mode
-
-LIBFUZZER_FLAGS=-Illvm-build/build/include $(SHARED_FLAGS) $(CLANG_COV_FLAGS) $(CLANG_SAN_FLAGS)
-AFL_FLAGS=-Iafl-build/build/include $(SHARED_FLAGS) -DINCLUDE_AFL_MAIN
-
-LIBFUZZER_LIBS=llvm-build/libbotan-2.a libFuzzer.a
-AFL_LIBS=afl-build/libbotan-2.a
-
-#AFL_CXX=AFL_USE_ASAN=1 afl-g++ -m32
-AFL_CXX=afl-g++
-AFL_CXX_TYPE=gcc
-CLANG_CXX=clang++
-
-LIBFUZZER_PROGS=$(patsubst %,bin/llvm_fuzz_%,$(FUZZERS))
-AFL_PROGS=$(patsubst %,bin/afl_fuzz_%,$(FUZZERS))
-
-all:
- @echo "make afl for AFL, llvm for libFuzzer"
-
-afl: dirs afl-build $(AFL_PROGS)
-
-llvm: dirs llvm-build $(LIBFUZZER_PROGS)
-
-bin/llvm_fuzz_%: jigs/%.cpp $(LIBFUZZER_LIBS)
- $(CLANG_CXX) $(LIBFUZZER_FLAGS) $< $(LIBFUZZER_LIBS) -o $@
-
-bin/afl_fuzz_%: jigs/%.cpp $(AFL_LIBS)
- $(AFL_CXX) $(AFL_FLAGS) $< $(AFL_LIBS) -o $@
-
-
-dirs:
- mkdir -p bin
- mkdir -p output
- mkdir -p corpus
-
-afl-build:
- ../../../configure.py $(CFG_FLAGS) --with-build-dir=afl-build --cc=$(AFL_CXX_TYPE) --cc-bin=$(AFL_CXX)
- make -j2 -f afl-build/Makefile afl-build/libbotan-2.a
-
-llvm-build:
- ../../../configure.py $(CFG_FLAGS) --with-build-dir=llvm-build --cc=clang --cc-bin=$(CLANG_CXX) --cc-abi-flags="$(CLANG_COV_FLAGS) $(CLANG_SAN_FLAGS)"
- make -j2 -f llvm-build/Makefile llvm-build/libbotan-2.a
-
-# libFuzzer default is max_len 64 this sets 140 but allows override via args=
-run_llvm_%: bin/llvm_fuzz_%
- $(eval FUZZER = $(subst bin/llvm_fuzz_,,$<))
- mkdir -p output/$(FUZZER)/llvm/queue
- mkdir -p output/$(FUZZER)/llvm/outputs
- $< -max_len=140 -artifact_prefix=output/$(FUZZER)/llvm/outputs/ output/$(FUZZER)/llvm/queue corpus/$(FUZZER) $(args)
-
-run_afl_%: bin/afl_fuzz_%
- $(eval FUZZER = $(subst bin/afl_fuzz_,,$<))
- mkdir -p output/$(FUZZER)/afl
- afl-fuzz $(args) -o output/$(FUZZER)/afl -i corpus/$(FUZZER) $<
-
-cmin_%: bin/afl_fuzz_%
- $(eval FUZZER = $(subst bin/afl_fuzz_,,$<))
- rm -rf cmin-dir
- mv corpus/$(FUZZER) cmin-dir
- -cp -n output/$(FUZZER)/afl/queue/* cmin-dir
- -cp -n output/$(FUZZER)/llvm/queue/* cmin-dir
- afl-cmin -i cmin-dir -o corpus/$(FUZZER) $<
- rm -rf cmin-dir
-
-clean:
- rm -f $(LIBFUZZER_PROGS) $(AFL_PROGS)
-
-clean_builds: clean
- rm -rf afl-build llvm-build
-
-libFuzzer:
- svn co http://llvm.org/svn/llvm-project/compiler-rt/trunk/lib/fuzzer libFuzzer
-
-libFuzzer.a: libFuzzer
- cd libFuzzer && clang -c -g -O2 -std=c++11 *.cpp
- ar cr libFuzzer.a libFuzzer/*.o
-
-update:
- svn co http://llvm.org/svn/llvm-project/compiler-rt/trunk/lib/fuzzer libFuzzer
diff --git a/src/extra_tests/fuzzers/readme.txt b/src/extra_tests/fuzzers/readme.txt
deleted file mode 100644
index 1bee1a785..000000000
--- a/src/extra_tests/fuzzers/readme.txt
+++ /dev/null
@@ -1,49 +0,0 @@
-
-The code in this directory is for testing various message decoders and
-math functions using the fuzzers AFL (http://lcamtuf.coredump.cx/afl/)
-and libFuzzer (http://llvm.org/docs/LibFuzzer.html).
-
-To build for AFL, run
-
- make afl
-
-For libFuzzer
-
- make llvm
-
-To add a new fuzzer, create a new file in jigs/, include "driver.h",
-and implement the function with the signature
-
-void fuzz(const uint8_t buf[], size_t len);
-
-This function should abort/crash if something is incorrect.
-
-Run it with
-
-make run_{llvm,afl}_{what}
-
-like in
-
-make run_llvm_crl
-make run_afl_tls_client
-
-You can pass args to the fuzzer process using args=
-
-make args=-max_len=4000 run_llvm_tls_client
-
-The fuzzer entry point assumes no more than 4K of input. The base
-libFuzzer default max len is 64 bytes, the makefile sets it to 140 as
-default.
-
-Use
-
-make cmin_redc_p384
-
-to run afl-cmin to minimize and merge the LLVM and AFL outputs back to
-the corpus directory.
-
-TODO:
-
-- KLEE (https://klee.github.io)
-- DFSan (http://clang.llvm.org/docs/DataFlowSanitizer.html)
-- More jigs
diff --git a/src/extra_tests/fuzzers/jigs/ber_decode.cpp b/src/fuzzer/asn1.cpp
index 6ec9cadba..b0ea553e5 100644
--- a/src/extra_tests/fuzzers/jigs/ber_decode.cpp
+++ b/src/fuzzer/asn1.cpp
@@ -1,25 +1,22 @@
/*
-* (C) 2016 Jack Lloyd
+* (C) 2016,2017 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#include "driver.h"
+#include "fuzzers.h"
#include <botan/ber_dec.h>
void fuzz(const uint8_t in[], size_t len)
{
- if(len > 4096)
- return;
-
try
{
- DataSource_Memory input(in, len);
- BER_Decoder dec(input);
+ Botan::DataSource_Memory input(in, len);
+ Botan::BER_Decoder dec(input);
while(dec.more_items())
{
- BER_Object obj;
+ Botan::BER_Object obj;
dec.get_next(obj);
}
}
diff --git a/src/extra_tests/fuzzers/jigs/bn_sqr.cpp b/src/fuzzer/bn_sqr.cpp
index aa76067f7..f507c4a79 100644
--- a/src/extra_tests/fuzzers/jigs/bn_sqr.cpp
+++ b/src/fuzzer/bn_sqr.cpp
@@ -4,7 +4,7 @@
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#include "driver.h"
+#include "fuzzers.h"
#include <botan/bigint.h>
#include <botan/numthry.h>
diff --git a/src/extra_tests/fuzzers/jigs/cert.cpp b/src/fuzzer/cert.cpp
index 5620a4700..3b40020df 100644
--- a/src/extra_tests/fuzzers/jigs/cert.cpp
+++ b/src/fuzzer/cert.cpp
@@ -3,19 +3,19 @@
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#include "driver.h"
+#include "fuzzers.h"
#include <botan/x509cert.h>
void fuzz(const uint8_t in[], size_t len)
{
- if(len > 8192)
+ if(len > max_fuzzer_input_size)
return;
try
{
- DataSource_Memory input(in, len);
- X509_Certificate cert(input);
+ Botan::DataSource_Memory input(in, len);
+ Botan::X509_Certificate cert(input);
}
catch(Botan::Exception& e) { }
}
diff --git a/src/extra_tests/fuzzers/jigs/crl.cpp b/src/fuzzer/crl.cpp
index b3157e5fe..63699b9b3 100644
--- a/src/extra_tests/fuzzers/jigs/crl.cpp
+++ b/src/fuzzer/crl.cpp
@@ -3,19 +3,16 @@
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#include "driver.h"
+#include "fuzzers.h"
#include <botan/x509_crl.h>
void fuzz(const uint8_t in[], size_t len)
{
- if(len > 4096)
- return;
-
try
{
- DataSource_Memory input(in, len);
- X509_CRL crl(input);
+ Botan::DataSource_Memory input(in, len);
+ Botan::X509_CRL crl(input);
}
- catch(Botan::Exception& e) { }
+ catch(Botan::Exception& e) {}
}
diff --git a/src/extra_tests/fuzzers/jigs/divide.cpp b/src/fuzzer/divide.cpp
index 4ff50a680..01ec14e28 100644
--- a/src/extra_tests/fuzzers/jigs/divide.cpp
+++ b/src/fuzzer/divide.cpp
@@ -3,7 +3,7 @@
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#include "driver.h"
+#include "fuzzers.h"
#include <botan/divide.h>
void fuzz(const uint8_t in[], size_t len)
@@ -11,18 +11,18 @@ void fuzz(const uint8_t in[], size_t len)
if(len % 2 == 1 || len > 2*4096/8)
return;
- const BigInt x = BigInt::decode(in, len / 2);
- const BigInt y = BigInt::decode(in + len / 2, len / 2);
+ const Botan::BigInt x = Botan::BigInt::decode(in, len / 2);
+ const Botan::BigInt y = Botan::BigInt::decode(in + len / 2, len / 2);
if(y == 0)
return;
- BigInt q, r;
+ Botan::BigInt q, r;
Botan::divide(x, y, q, r);
FUZZER_ASSERT_TRUE(r < y);
- BigInt z = q*y + r;
+ Botan::BigInt z = q*y + r;
FUZZER_ASSERT_EQUAL(z, x);
}
diff --git a/src/extra_tests/fuzzers/jigs/ecc_bp256.cpp b/src/fuzzer/ecc_bp256.cpp
index 07833c639..4c1186f06 100644
--- a/src/extra_tests/fuzzers/jigs/ecc_bp256.cpp
+++ b/src/fuzzer/ecc_bp256.cpp
@@ -3,7 +3,7 @@
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#include "driver.h"
+#include "fuzzers.h"
#include "ecc_helper.h"
void fuzz(const uint8_t in[], size_t len)
@@ -11,6 +11,6 @@ void fuzz(const uint8_t in[], size_t len)
if(len > 2*256/8)
return;
- static EC_Group bp256("brainpool256r1");
+ static Botan::EC_Group bp256("brainpool256r1");
return check_ecc_math(bp256, in, len);
}
diff --git a/src/extra_tests/fuzzers/jigs/ecc_helper.h b/src/fuzzer/ecc_helper.h
index fb502452a..c9b3a6604 100644
--- a/src/extra_tests/fuzzers/jigs/ecc_helper.h
+++ b/src/fuzzer/ecc_helper.h
@@ -3,37 +3,24 @@
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
+
#ifndef ECC_HELPERS_H__
#define ECC_HELPERS_H__
-#include "driver.h"
+#include "fuzzers.h"
#include <botan/curve_gfp.h>
#include <botan/ec_group.h>
#include <botan/reducer.h>
-void check_redc(std::function<void (BigInt&, secure_vector<word>&)> redc_fn,
- const Modular_Reducer& redc,
- const BigInt& prime,
- const BigInt& x)
- {
- const Botan::BigInt v1 = x % prime;
- const Botan::BigInt v2 = redc.reduce(x);
-
- Botan::secure_vector<Botan::word> ws;
- Botan::BigInt v3 = x;
- redc_fn(v3, ws);
+namespace {
- FUZZER_ASSERT_EQUAL(v1, v2);
- FUZZER_ASSERT_EQUAL(v2, v3);
- }
-
-inline std::ostream& operator<<(std::ostream& o, const PointGFp& point)
+inline std::ostream& operator<<(std::ostream& o, const Botan::PointGFp& point)
{
o << point.get_affine_x() << "," << point.get_affine_y();
return o;
}
-void check_ecc_math(const EC_Group& group,
+void check_ecc_math(const Botan::EC_Group& group,
const uint8_t in[], size_t len)
{
// These depend only on the group, which is also static
@@ -41,8 +28,8 @@ void check_ecc_math(const EC_Group& group,
static Botan::Blinded_Point_Multiply blind(base_point, group.get_order(), 4);
const size_t hlen = len / 2;
- const BigInt a = BigInt::decode(in, hlen);
- const BigInt b = BigInt::decode(in + hlen, len - hlen);
+ const Botan::BigInt a = Botan::BigInt::decode(in, hlen);
+ const Botan::BigInt b = Botan::BigInt::decode(in + hlen, len - hlen);
const Botan::BigInt c = a + b;
@@ -66,4 +53,6 @@ void check_ecc_math(const EC_Group& group,
FUZZER_ASSERT_EQUAL(S1, A1);
}
+}
+
#endif
diff --git a/src/extra_tests/fuzzers/jigs/ecc_p256.cpp b/src/fuzzer/ecc_p256.cpp
index f13104fda..c00be71b6 100644
--- a/src/extra_tests/fuzzers/jigs/ecc_p256.cpp
+++ b/src/fuzzer/ecc_p256.cpp
@@ -3,13 +3,13 @@
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#include "driver.h"
+#include "fuzzers.h"
#include "ecc_helper.h"
void fuzz(const uint8_t in[], size_t len)
{
if(len > 2*256/8)
return;
- static EC_Group p256("secp256r1");
+ static Botan::EC_Group p256("secp256r1");
return check_ecc_math(p256, in, len);
}
diff --git a/src/extra_tests/fuzzers/jigs/ecc_p384.cpp b/src/fuzzer/ecc_p384.cpp
index 47826e1d6..1b58da958 100644
--- a/src/extra_tests/fuzzers/jigs/ecc_p384.cpp
+++ b/src/fuzzer/ecc_p384.cpp
@@ -3,13 +3,13 @@
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#include "driver.h"
+#include "fuzzers.h"
#include "ecc_helper.h"
void fuzz(const uint8_t in[], size_t len)
{
if(len > 2*384/8)
return;
- static EC_Group p384("secp384r1");
+ static Botan::EC_Group p384("secp384r1");
return check_ecc_math(p384, in, len);
}
diff --git a/src/extra_tests/fuzzers/jigs/ecc_p521.cpp b/src/fuzzer/ecc_p521.cpp
index c2d1e36bb..3b9ed2d5c 100644
--- a/src/extra_tests/fuzzers/jigs/ecc_p521.cpp
+++ b/src/fuzzer/ecc_p521.cpp
@@ -3,13 +3,13 @@
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#include "driver.h"
+#include "fuzzers.h"
#include "ecc_helper.h"
void fuzz(const uint8_t in[], size_t len)
{
if(len > 2*(521+7)/8)
return;
- static EC_Group p521("secp521r1");
+ static Botan::EC_Group p521("secp521r1");
return check_ecc_math(p521, in, len);
}
diff --git a/src/extra_tests/fuzzers/jigs/driver.h b/src/fuzzer/fuzzers.h
index 08fffd0c1..2f1b1346d 100644
--- a/src/extra_tests/fuzzers/jigs/driver.h
+++ b/src/fuzzer/fuzzers.h
@@ -1,25 +1,30 @@
/*
-* (C) 2015,2016 Jack Lloyd
+* (C) 2015,2016,2017 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#ifndef FUZZER_DRIVER_H_
-#define FUZZER_DRIVER_H_
+#ifndef BOTAN_FUZZER_DRIVER_H__
+#define BOTAN_FUZZER_DRIVER_H__
#include <stdint.h>
+#include <stdlib.h> // for setenv
#include <iostream>
#include <vector>
-#include <stdlib.h> // for setenv
#include <botan/exceptn.h>
-#include <botan/rng.h>
-#include <botan/chacha.h>
+#include <botan/chacha_rng.h>
+
+#if defined(BOTAN_FUZZER_IS_AFL) && !defined(__AFL_COMPILER)
+ #error "Build configured for AFL but not being compiled by AFL compiler"
+#endif
-using namespace Botan;
+static const size_t max_fuzzer_input_size = 8192;
extern void fuzz(const uint8_t in[], size_t len);
+extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv);
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t in[], size_t len);
-extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv)
+extern "C" int LLVMFuzzerInitialize(int *, char ***)
{
/*
* This disables the mlock pool, as overwrites within the pool are
@@ -32,68 +37,18 @@ extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv)
// Called by main() in libFuzzer or in main for AFL below
extern "C" int LLVMFuzzerTestOneInput(const uint8_t in[], size_t len)
{
- fuzz(in, len);
- return 0;
- }
-
-#if defined(INCLUDE_AFL_MAIN)
-
-// Read stdin for AFL
-
-int main(int argc, char* argv[])
- {
- const size_t max_read = 4096;
-
- LLVMFuzzerInitialize(&argc, &argv);
-
-#if defined(__AFL_LOOP)
- while(__AFL_LOOP(1000))
-#endif
+ if(len <= max_fuzzer_input_size)
{
- std::vector<uint8_t> buf(max_read);
- std::cin.read((char*)buf.data(), buf.size());
- size_t got = std::cin.gcount();
-
- buf.resize(got);
- buf.shrink_to_fit();
-
- fuzz(buf.data(), got);
+ fuzz(in, len);
}
+ return 0;
}
-#endif
-
// Some helpers for the fuzzer jigs
inline Botan::RandomNumberGenerator& fuzzer_rng()
{
- class ChaCha20_RNG : public Botan::RandomNumberGenerator
- {
- public:
- std::string name() const override { return "ChaCha20_RNG"; }
- void clear() override { /* ignored */ }
-
- void randomize(uint8_t out[], size_t len) override
- {
- Botan::clear_mem(out, len);
- m_chacha.cipher1(out, len);
- }
-
- bool is_seeded() const override { return true; }
-
- void add_entropy(const uint8_t[], size_t) override { /* ignored */ }
-
- ChaCha20_RNG()
- {
- std::vector<uint8_t> seed(32, 0x82);
- m_chacha.set_key(seed);
- }
-
- private:
- Botan::ChaCha m_chacha;
- };
-
- static ChaCha20_RNG rng;
+ static Botan::ChaCha_RNG rng(Botan::secure_vector<uint8_t>(32));
return rng;
}
@@ -112,4 +67,29 @@ inline Botan::RandomNumberGenerator& fuzzer_rng()
abort(); \
} } while(0)
+#if defined(BOTAN_FUZZER_IS_AFL) || defined(BOTAN_FUZZER_IS_TEST)
+
+/* Stub for AFL */
+
+int main(int argc, char* argv[])
+ {
+ LLVMFuzzerInitialize(&argc, &argv);
+
+#if defined(__AFL_LOOP)
+ while(__AFL_LOOP(1000))
+#endif
+ {
+ std::vector<uint8_t> buf(max_fuzzer_input_size);
+ std::cin.read((char*)buf.data(), buf.size());
+ const size_t got = std::cin.gcount();
+
+ buf.resize(got);
+ buf.shrink_to_fit();
+
+ LLVMFuzzerTestOneInput(buf.data(), got);
+ }
+ }
+
+#endif
+
#endif
diff --git a/src/extra_tests/fuzzers/jigs/invert.cpp b/src/fuzzer/invert.cpp
index 63c140139..08e8229b8 100644
--- a/src/extra_tests/fuzzers/jigs/invert.cpp
+++ b/src/fuzzer/invert.cpp
@@ -3,16 +3,18 @@
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#include "driver.h"
+#include "fuzzers.h"
#include <botan/numthry.h>
-BigInt inverse_mod_ref(const BigInt& n, const BigInt& mod)
+namespace {
+
+Botan::BigInt inverse_mod_ref(const Botan::BigInt& n, const Botan::BigInt& mod)
{
if(n == 0)
return 0;
- BigInt u = mod, v = n;
- BigInt B = 0, D = 1;
+ Botan::BigInt u = mod, v = n;
+ Botan::BigInt B = 0, D = 1;
while(u.is_nonzero())
{
@@ -48,23 +50,24 @@ BigInt inverse_mod_ref(const BigInt& n, const BigInt& mod)
return D;
}
+}
void fuzz(const uint8_t in[], size_t len)
{
if(len % 2 == 1 || len > 2*4096/8)
return;
- const BigInt x = BigInt::decode(in, len / 2);
- BigInt mod = BigInt::decode(in + len / 2, len / 2);
+ const Botan::BigInt x = Botan::BigInt::decode(in, len / 2);
+ Botan::BigInt mod = Botan::BigInt::decode(in + len / 2, len / 2);
mod.set_bit(0);
if(mod < 3 || x >= mod)
return;
- BigInt ref = inverse_mod_ref(x, mod);
- BigInt ct = ct_inverse_mod_odd_modulus(x, mod);
- //BigInt mon = normalized_montgomery_inverse(x, mod);
+ Botan::BigInt ref = inverse_mod_ref(x, mod);
+ Botan::BigInt ct = Botan::ct_inverse_mod_odd_modulus(x, mod);
+ //Botan::BigInt mon = Botan::normalized_montgomery_inverse(x, mod);
if(ref != ct)
{
diff --git a/src/extra_tests/fuzzers/jigs/ocsp.cpp b/src/fuzzer/ocsp.cpp
index 7cf2d91b0..0db265b8d 100644
--- a/src/extra_tests/fuzzers/jigs/ocsp.cpp
+++ b/src/fuzzer/ocsp.cpp
@@ -3,15 +3,15 @@
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#include "driver.h"
+#include "fuzzers.h"
#include <botan/ocsp.h>
void fuzz(const uint8_t in[], size_t len)
{
try
{
- OCSP::Response response(in, len);
+ Botan::OCSP::Response response(in, len);
}
catch(Botan::Exception& e) { }
}
diff --git a/src/extra_tests/fuzzers/jigs/os2ecp.cpp b/src/fuzzer/os2ecp.cpp
index 61ce1bd7b..dba6dbdfe 100644
--- a/src/extra_tests/fuzzers/jigs/os2ecp.cpp
+++ b/src/fuzzer/os2ecp.cpp
@@ -3,31 +3,35 @@
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#include "driver.h"
+#include "fuzzers.h"
#include <botan/ec_group.h>
#include <botan/point_gfp.h>
-void check_os2ecp(const EC_Group& group, const uint8_t in[], size_t len)
+namespace {
+
+void check_os2ecp(const Botan::EC_Group& group, const uint8_t in[], size_t len)
{
try
{
- PointGFp point = OS2ECP(in, len, group.get_curve());
+ Botan::PointGFp point = Botan::OS2ECP(in, len, group.get_curve());
}
catch(Botan::Exception& e) {}
}
+}
+
void fuzz(const uint8_t in[], size_t len)
{
if(len >= 256)
return;
- static EC_Group p192("secp192r1");
- static EC_Group p224("secp224r1");
- static EC_Group p256("secp256r1");
- static EC_Group p384("secp384r1");
- static EC_Group p521("secp521r1");
- static EC_Group bp256("brainpool256r1");
- static EC_Group bp512("brainpool512r1");
+ static Botan::EC_Group p192("secp192r1");
+ static Botan::EC_Group p224("secp224r1");
+ static Botan::EC_Group p256("secp256r1");
+ static Botan::EC_Group p384("secp384r1");
+ static Botan::EC_Group p521("secp521r1");
+ static Botan::EC_Group bp256("brainpool256r1");
+ static Botan::EC_Group bp512("brainpool512r1");
check_os2ecp(p192, in, len);
check_os2ecp(p224, in, len);
diff --git a/src/extra_tests/fuzzers/jigs/pkcs1.cpp b/src/fuzzer/pkcs1.cpp
index 8a16d17e5..a0323d2b2 100644
--- a/src/extra_tests/fuzzers/jigs/pkcs1.cpp
+++ b/src/fuzzer/pkcs1.cpp
@@ -3,12 +3,14 @@
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#include "driver.h"
+#include "fuzzers.h"
#include <botan/eme_pkcs.h>
#include <botan/hex.h>
-secure_vector<byte> simple_pkcs1_unpad(const byte in[], size_t len)
+namespace {
+
+std::vector<uint8_t> simple_pkcs1_unpad(const uint8_t in[], size_t len)
{
if(len < 10)
throw Botan::Decoding_Error("bad len");
@@ -22,24 +24,27 @@ secure_vector<byte> simple_pkcs1_unpad(const byte in[], size_t len)
{
if(i < 10) // at least 8 padding bytes required
throw Botan::Decoding_Error("insufficient padding bytes");
- return secure_vector<byte>(in + i + 1, in + len);
+ return std::vector<uint8_t>(in + i + 1, in + len);
}
}
throw Botan::Decoding_Error("delim not found");
}
+}
+
void fuzz(const uint8_t in[], size_t len)
{
- static EME_PKCS1v15 pkcs1;
+ static Botan::EME_PKCS1v15 pkcs1;
- secure_vector<byte> lib_result, ref_result;
+ Botan::secure_vector<uint8_t> lib_result;
+ std::vector<uint8_t> ref_result;
bool lib_rejected = false, ref_rejected = false;
try
{
- byte valid_mask = 0;
- secure_vector<byte> decoded = ((EME*)&pkcs1)->unpad(valid_mask, in, len);
+ uint8_t valid_mask = 0;
+ Botan::secure_vector<uint8_t> decoded = (static_cast<Botan::EME*>(&pkcs1))->unpad(valid_mask, in, len);
if(valid_mask == 0)
lib_rejected = true;
@@ -54,7 +59,7 @@ void fuzz(const uint8_t in[], size_t len)
{
ref_result = simple_pkcs1_unpad(in, len);
}
- catch(Botan::Decoding_Error& e) { ref_rejected = true; /*printf("%s\n", e.what());*/ }
+ catch(Botan::Decoding_Error& e) { ref_rejected = true; }
if(lib_rejected == ref_rejected)
{
@@ -65,12 +70,12 @@ void fuzz(const uint8_t in[], size_t len)
if(lib_rejected == true && ref_rejected == false)
{
std::cerr << "Library rejected input accepted by ref\n";
- std::cerr << "Ref decoded " << hex_encode(ref_result) << "\n";
+ std::cerr << "Ref decoded " << Botan::hex_encode(ref_result) << "\n";
}
else if(ref_rejected == true && lib_rejected == false)
{
std::cerr << "Library accepted input reject by ref\n";
- std::cerr << "Lib decoded " << hex_encode(lib_result) << "\n";
+ std::cerr << "Lib decoded " << Botan::hex_encode(lib_result) << "\n";
}
abort();
diff --git a/src/extra_tests/fuzzers/jigs/pkcs8.cpp b/src/fuzzer/pkcs8.cpp
index 47c0068ad..ad43d6f3e 100644
--- a/src/extra_tests/fuzzers/jigs/pkcs8.cpp
+++ b/src/fuzzer/pkcs8.cpp
@@ -3,7 +3,7 @@
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#include "driver.h"
+#include "fuzzers.h"
#include <botan/pkcs8.h>
@@ -11,8 +11,9 @@ void fuzz(const uint8_t in[], size_t len)
{
try
{
- DataSource_Memory input(in, len);
- std::unique_ptr<Private_Key> key(PKCS8::load_key(input, fuzzer_rng()));
+ Botan::DataSource_Memory input(in, len);
+ Botan::Null_RNG null_rng;
+ std::unique_ptr<Botan::Private_Key> key(Botan::PKCS8::load_key(input, null_rng));
}
catch(Botan::Exception& e) { }
}
diff --git a/src/extra_tests/fuzzers/jigs/pow_mod.cpp b/src/fuzzer/pow_mod.cpp
index c97dd78cd..2244c2004 100644
--- a/src/extra_tests/fuzzers/jigs/pow_mod.cpp
+++ b/src/fuzzer/pow_mod.cpp
@@ -4,12 +4,17 @@
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#include "driver.h"
+#include "fuzzers.h"
#include <botan/numthry.h>
#include <botan/reducer.h>
#include <botan/pow_mod.h>
-BigInt simple_power_mod(BigInt x, BigInt n, const BigInt& p, const Modular_Reducer& mod_p)
+namespace {
+
+Botan::BigInt simple_power_mod(Botan::BigInt x,
+ Botan::BigInt n,
+ const Botan::BigInt& p,
+ const Botan::Modular_Reducer& mod_p)
{
if(n == 0)
{
@@ -18,7 +23,7 @@ BigInt simple_power_mod(BigInt x, BigInt n, const BigInt& p, const Modular_Reduc
return 1;
}
- BigInt y = 1;
+ Botan::BigInt y = 1;
while(n > 1)
{
@@ -32,22 +37,24 @@ BigInt simple_power_mod(BigInt x, BigInt n, const BigInt& p, const Modular_Reduc
return mod_p.multiply(x, y);
}
+}
+
void fuzz(const uint8_t in[], size_t len)
{
static const size_t p_bits = 1024;
- static const BigInt p = random_prime(fuzzer_rng(), p_bits);
- static Modular_Reducer mod_p(p);
+ static const Botan::BigInt p = random_prime(fuzzer_rng(), p_bits);
+ static Botan::Modular_Reducer mod_p(p);
if(len == 0 || len > p_bits/8)
return;
try
{
- const BigInt g = BigInt::decode(in, len / 2);
- const BigInt x = BigInt::decode(in + len / 2, len / 2);
+ const Botan::BigInt g = Botan::BigInt::decode(in, len / 2);
+ const Botan::BigInt x = Botan::BigInt::decode(in + len / 2, len / 2);
- const BigInt ref = simple_power_mod(g, x, p, mod_p);
- const BigInt z = Botan::power_mod(g, x, p);
+ const Botan::BigInt ref = simple_power_mod(g, x, p, mod_p);
+ const Botan::BigInt z = Botan::power_mod(g, x, p);
if(ref != z)
{
diff --git a/src/fuzzer/redc_helper.h b/src/fuzzer/redc_helper.h
new file mode 100644
index 000000000..4fc33894a
--- /dev/null
+++ b/src/fuzzer/redc_helper.h
@@ -0,0 +1,33 @@
+/*
+* (C) 2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_FUZZ_REDC_HELPERS_H__
+#define BOTAN_FUZZ_REDC_HELPERS_H__
+
+#include "fuzzers.h"
+#include <botan/reducer.h>
+
+namespace {
+
+void check_redc(std::function<void (Botan::BigInt&, Botan::secure_vector<Botan::word>&)> redc_fn,
+ const Botan::Modular_Reducer& redc,
+ const Botan::BigInt& prime,
+ const Botan::BigInt& x)
+ {
+ const Botan::BigInt v1 = x % prime;
+ const Botan::BigInt v2 = redc.reduce(x);
+
+ Botan::secure_vector<Botan::word> ws;
+ Botan::BigInt v3 = x;
+ redc_fn(v3, ws);
+
+ FUZZER_ASSERT_EQUAL(v1, v2);
+ FUZZER_ASSERT_EQUAL(v2, v3);
+ }
+
+}
+
+#endif
diff --git a/src/extra_tests/fuzzers/jigs/redc_p192.cpp b/src/fuzzer/redc_p192.cpp
index 9bece4595..e1f7c753f 100644
--- a/src/extra_tests/fuzzers/jigs/redc_p192.cpp
+++ b/src/fuzzer/redc_p192.cpp
@@ -4,8 +4,8 @@
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#include "driver.h"
-#include "ecc_helper.h"
+#include "fuzzers.h"
+#include "redc_helper.h"
#include <botan/curve_nistp.h>
void fuzz(const uint8_t in[], size_t len)
@@ -13,8 +13,8 @@ void fuzz(const uint8_t in[], size_t len)
if(len > 2*192/8)
return;
- static const BigInt& prime = Botan::prime_p192();
- static const BigInt prime_2 = prime * prime;
+ static const Botan::BigInt& prime = Botan::prime_p192();
+ static const Botan::BigInt prime_2 = prime * prime;
static Botan::Modular_Reducer prime_redc(prime);
Botan::BigInt x = Botan::BigInt::decode(in, len);
diff --git a/src/extra_tests/fuzzers/jigs/redc_p224.cpp b/src/fuzzer/redc_p224.cpp
index 637d9e6fd..a8a4d5d72 100644
--- a/src/extra_tests/fuzzers/jigs/redc_p224.cpp
+++ b/src/fuzzer/redc_p224.cpp
@@ -4,14 +4,14 @@
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#include "driver.h"
-#include "ecc_helper.h"
+#include "fuzzers.h"
+#include "redc_helper.h"
#include <botan/curve_nistp.h>
void fuzz(const uint8_t in[], size_t len)
{
- static const BigInt& prime = Botan::prime_p224();
- static const BigInt prime_2 = prime * prime;
+ static const Botan::BigInt& prime = Botan::prime_p224();
+ static const Botan::BigInt prime_2 = prime * prime;
static Botan::Modular_Reducer prime_redc(prime);
Botan::BigInt x = Botan::BigInt::decode(in, len);
diff --git a/src/extra_tests/fuzzers/jigs/redc_p256.cpp b/src/fuzzer/redc_p256.cpp
index cbb7f4fef..b8d78e7bb 100644
--- a/src/extra_tests/fuzzers/jigs/redc_p256.cpp
+++ b/src/fuzzer/redc_p256.cpp
@@ -4,8 +4,8 @@
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#include "driver.h"
-#include "ecc_helper.h"
+#include "fuzzers.h"
+#include "redc_helper.h"
#include <botan/curve_nistp.h>
void fuzz(const uint8_t in[], size_t len)
@@ -13,8 +13,8 @@ void fuzz(const uint8_t in[], size_t len)
if(len > 2*256/8)
return;
- static const BigInt& prime = Botan::prime_p256();
- static const BigInt prime_2 = prime * prime;
+ static const Botan::BigInt& prime = Botan::prime_p256();
+ static const Botan::BigInt prime_2 = prime * prime;
static Botan::Modular_Reducer prime_redc(prime);
Botan::BigInt x = Botan::BigInt::decode(in, len);
diff --git a/src/extra_tests/fuzzers/jigs/redc_p384.cpp b/src/fuzzer/redc_p384.cpp
index 3b990fb63..35e3ccfee 100644
--- a/src/extra_tests/fuzzers/jigs/redc_p384.cpp
+++ b/src/fuzzer/redc_p384.cpp
@@ -4,8 +4,8 @@
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#include "driver.h"
-#include "ecc_helper.h"
+#include "fuzzers.h"
+#include "redc_helper.h"
#include <botan/curve_nistp.h>
void fuzz(const uint8_t in[], size_t len)
@@ -13,8 +13,8 @@ void fuzz(const uint8_t in[], size_t len)
if(len > 2*384/8)
return;
- static const BigInt& prime = Botan::prime_p384();
- static const BigInt prime_2 = prime * prime;
+ static const Botan::BigInt& prime = Botan::prime_p384();
+ static const Botan::BigInt prime_2 = prime * prime;
static Botan::Modular_Reducer prime_redc(prime);
Botan::BigInt x = Botan::BigInt::decode(in, len);
diff --git a/src/extra_tests/fuzzers/jigs/redc_p521.cpp b/src/fuzzer/redc_p521.cpp
index 5142a44c2..c6c5d262b 100644
--- a/src/extra_tests/fuzzers/jigs/redc_p521.cpp
+++ b/src/fuzzer/redc_p521.cpp
@@ -4,8 +4,8 @@
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#include "driver.h"
-#include "ecc_helper.h"
+#include "fuzzers.h"
+#include "redc_helper.h"
#include <botan/curve_nistp.h>
void fuzz(const uint8_t in[], size_t len)
@@ -13,8 +13,8 @@ void fuzz(const uint8_t in[], size_t len)
if(len > 2*(521+7)/8)
return;
- static const BigInt& prime = Botan::prime_p521();
- static const BigInt prime_2 = prime * prime;
+ static const Botan::BigInt& prime = Botan::prime_p521();
+ static const Botan::BigInt prime_2 = prime * prime;
static Botan::Modular_Reducer prime_redc(prime);
Botan::BigInt x = Botan::BigInt::decode(in, len);
diff --git a/src/extra_tests/fuzzers/jigs/ressol.cpp b/src/fuzzer/ressol.cpp
index 6fbb85690..17ba88b8b 100644
--- a/src/extra_tests/fuzzers/jigs/ressol.cpp
+++ b/src/fuzzer/ressol.cpp
@@ -4,7 +4,7 @@
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#include "driver.h"
+#include "fuzzers.h"
#include <botan/numthry.h>
#include <botan/reducer.h>
@@ -12,21 +12,21 @@ void fuzz(const uint8_t in[], size_t len)
{
// Ressol is mostly used for ECC point decompression so best to test smaller sizes
static const size_t p_bits = 256;
- static const BigInt p = random_prime(fuzzer_rng(), p_bits);
- static const Modular_Reducer mod_p(p);
+ static const Botan::BigInt p = random_prime(fuzzer_rng(), p_bits);
+ static const Botan::Modular_Reducer mod_p(p);
if(len > p_bits / 8)
return;
try
{
- const BigInt a = BigInt::decode(in, len);
- BigInt a_sqrt = Botan::ressol(a, p);
+ const Botan::BigInt a = Botan::BigInt::decode(in, len);
+ Botan::BigInt a_sqrt = Botan::ressol(a, p);
if(a_sqrt > 0)
{
- const BigInt a_redc = mod_p.reduce(a);
- const BigInt z = mod_p.square(a_sqrt);
+ const Botan::BigInt a_redc = mod_p.reduce(a);
+ const Botan::BigInt z = mod_p.square(a_sqrt);
if(z != a_redc)
{
diff --git a/src/extra_tests/fuzzers/jigs/tls_client.cpp b/src/fuzzer/tls_client.cpp
index d3fbd069c..197e97928 100644
--- a/src/extra_tests/fuzzers/jigs/tls_client.cpp
+++ b/src/fuzzer/tls_client.cpp
@@ -4,17 +4,17 @@
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#include "driver.h"
+#include "fuzzers.h"
#include <botan/tls_client.h>
-class Fuzzer_TLS_Client_Creds : public Credentials_Manager
+class Fuzzer_TLS_Client_Creds : public Botan::Credentials_Manager
{
public:
std::string psk_identity_hint(const std::string&, const std::string&) override { return "psk_hint"; }
std::string psk_identity(const std::string&, const std::string&, const std::string&) override { return "psk_id"; }
- SymmetricKey psk(const std::string&, const std::string&, const std::string&) override
+ Botan::SymmetricKey psk(const std::string&, const std::string&, const std::string&) override
{
- return SymmetricKey("AABBCCDDEEFF00112233445566778899");
+ return Botan::SymmetricKey("AABBCCDDEEFF00112233445566778899");
}
};
@@ -23,18 +23,18 @@ void fuzz(const uint8_t in[], size_t len)
if(len == 0)
return;
- auto dev_null = [](const byte[], size_t) {};
+ auto dev_null = [](const uint8_t[], size_t) {};
- auto ignore_alerts = [](TLS::Alert, const byte[], size_t) {};
- auto ignore_hs = [](const TLS::Session&) { abort(); return true; };
+ auto ignore_alerts = [](Botan::TLS::Alert, const uint8_t[], size_t) {};
+ auto ignore_hs = [](const Botan::TLS::Session&) { abort(); return true; };
- TLS::Session_Manager_Noop session_manager;
- TLS::Policy policy;
- TLS::Protocol_Version client_offer = TLS::Protocol_Version::TLS_V12;
- TLS::Server_Information info("server.name", 443);
+ Botan::TLS::Session_Manager_Noop session_manager;
+ Botan::TLS::Policy policy;
+ Botan::TLS::Protocol_Version client_offer = Botan::TLS::Protocol_Version::TLS_V12;
+ Botan::TLS::Server_Information info("server.name", 443);
Fuzzer_TLS_Client_Creds creds;
- TLS::Client client(dev_null,
+ Botan::TLS::Client client(dev_null,
dev_null,
ignore_alerts,
ignore_hs,
diff --git a/src/extra_tests/fuzzers/jigs/tls_client_hello.cpp b/src/fuzzer/tls_client_hello.cpp
index 7c95c7db3..28c77c9b6 100644
--- a/src/extra_tests/fuzzers/jigs/tls_client_hello.cpp
+++ b/src/fuzzer/tls_client_hello.cpp
@@ -3,7 +3,8 @@
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#include "driver.h"
+
+#include "fuzzers.h"
#include <botan/tls_messages.h>
void fuzz(const uint8_t in[], size_t len)
diff --git a/src/extra_tests/fuzzers/jigs/tls_server.cpp b/src/fuzzer/tls_server.cpp
index a4e0d5f00..54586595f 100644
--- a/src/extra_tests/fuzzers/jigs/tls_server.cpp
+++ b/src/fuzzer/tls_server.cpp
@@ -4,7 +4,7 @@
* Botan is released under the Simplified BSD License (see license.txt)
*/
-#include "driver.h"
+#include "fuzzers.h"
#include <botan/tls_server.h>
const char* fixed_rsa_key =
@@ -59,13 +59,13 @@ const char* fixed_rsa_cert =
"Dk02a/1AOJZdZReDbgXhlqaUx5pk/rzo4mDzvu5HSCeXmClz\n"
"-----END CERTIFICATE-----\n";
-class Fuzzer_TLS_Server_Creds : public Credentials_Manager
+class Fuzzer_TLS_Server_Creds : public Botan::Credentials_Manager
{
public:
Fuzzer_TLS_Server_Creds()
{
- DataSource_Memory cert_in(fixed_rsa_cert);
- DataSource_Memory key_in(fixed_rsa_key);
+ Botan::DataSource_Memory cert_in(fixed_rsa_cert);
+ Botan::DataSource_Memory key_in(fixed_rsa_key);
m_rsa_cert.reset(new Botan::X509_Certificate(cert_in));
//m_rsa_key.reset(Botan::PKCS8::load_key(key_in, fuzzer_rng());
@@ -73,8 +73,8 @@ class Fuzzer_TLS_Server_Creds : public Credentials_Manager
std::vector<Botan::X509_Certificate> cert_chain(
const std::vector<std::string>& algos,
- const std::string& type,
- const std::string& hostname) override
+ const std::string& /*type*/,
+ const std::string& /*hostname*/) override
{
std::vector<Botan::X509_Certificate> v;
@@ -90,7 +90,7 @@ class Fuzzer_TLS_Server_Creds : public Credentials_Manager
return v;
}
- Botan::Private_Key* private_key_for(const Botan::X509_Certificate& cert,
+ Botan::Private_Key* private_key_for(const Botan::X509_Certificate& /*cert*/,
const std::string& /*type*/,
const std::string& /*context*/) override
{
@@ -99,9 +99,9 @@ class Fuzzer_TLS_Server_Creds : public Credentials_Manager
std::string psk_identity_hint(const std::string&, const std::string&) override { return "psk_hint"; }
std::string psk_identity(const std::string&, const std::string&, const std::string&) override { return "psk_id"; }
- SymmetricKey psk(const std::string&, const std::string&, const std::string&) override
+ Botan::SymmetricKey psk(const std::string&, const std::string&, const std::string&) override
{
- return SymmetricKey("AABBCCDDEEFF00112233445566778899");
+ return Botan::SymmetricKey("AABBCCDDEEFF00112233445566778899");
}
private:
std::unique_ptr<Botan::X509_Certificate> m_rsa_cert;
@@ -113,14 +113,14 @@ void fuzz(const uint8_t in[], size_t len)
if(len == 0)
return;
- auto dev_null = [](const byte[], size_t) {};
+ auto dev_null = [](const uint8_t[], size_t) {};
- auto ignore_alerts = [](TLS::Alert, const byte[], size_t) {};
- auto ignore_hs = [](const TLS::Session&) { return true; };
+ auto ignore_alerts = [](Botan::TLS::Alert, const uint8_t[], size_t) {};
+ auto ignore_hs = [](const Botan::TLS::Session&) { return true; };
- TLS::Session_Manager_Noop session_manager;
- TLS::Policy policy;
- TLS::Server_Information info("server.name", 443);
+ Botan::TLS::Session_Manager_Noop session_manager;
+ Botan::TLS::Policy policy;
+ Botan::TLS::Server_Information info("server.name", 443);
Fuzzer_TLS_Server_Creds creds;
auto next_proto_fn = [](const std::vector<std::string>& protos) -> std::string {
@@ -132,7 +132,7 @@ void fuzz(const uint8_t in[], size_t len)
const bool is_datagram = (len % 2 == 0);
- TLS::Server server(dev_null,
+ Botan::TLS::Server server(dev_null,
dev_null,
ignore_alerts,
ignore_hs,
diff --git a/src/scripts/ci/travis/build.sh b/src/scripts/ci/travis/build.sh
index 36517738b..d2e35112e 100755
--- a/src/scripts/ci/travis/build.sh
+++ b/src/scripts/ci/travis/build.sh
@@ -23,6 +23,8 @@ elif [ "$BUILD_MODE" = "nist" ]; then
elif [ "$BUILD_MODE" = "sonarqube" ]; then
# No special flags required
CFG_FLAGS+=()
+elif [ "$BUILD_MODE" = "fuzzers" ]; then
+ CFG_FLAGS+=(--build-fuzzers=test --with-sanitizers --with-debug-info --disable-shared)
elif [ "$BUILD_MODE" = "parallel" ]; then
if [ "$CC" = "gcc" ]; then
@@ -137,6 +139,11 @@ else
time "${MAKE_CMD[@]}"
fi
+if [ "$BUILD_MODE" = "fuzzers" ]; then
+ make fuzzers
+ make fuzzer_corpus_zip
+fi
+
# post-build ccache stats
ccache --show-stats
@@ -171,9 +178,13 @@ if [ "$BUILD_MODE" = "sonarqube" ]; then
# When neither on master branch nor on a non-external pull request => nothing to do
fi
-if [ "$BUILD_MODE" = "sonarqube" ] || [ "$BUILD_MODE" = "docs" ] || \
+if [ "$BUILD_MODE" = "sonarqube" ] || [ "$BUILD_MODE" = "docs" ] ||
( [ "${BUILD_MODE:0:5}" = "cross" ] && [ "$TRAVIS_OS_NAME" = "osx" ] ); then
echo "Running tests disabled on this build type"
+
+elif [ "$BUILD_MODE" = "fuzzers" ]; then
+ # Test each fuzzer against its corpus
+ ./src/scripts/test_fuzzers.py fuzzer_corpus build/fuzzer
else
TEST_CMD=("${TEST_PREFIX[@]}" $TEST_EXE "${TEST_FLAGS[@]}")
echo "Running" "${TEST_CMD[@]}"
diff --git a/src/scripts/create_corpus_zip.py b/src/scripts/create_corpus_zip.py
new file mode 100755
index 000000000..5faee3b52
--- /dev/null
+++ b/src/scripts/create_corpus_zip.py
@@ -0,0 +1,48 @@
+#!/usr/bin/python
+
+# These is used to create fuzzer corpus zip files
+
+# This is primarily used by OSS-Fuzz but might be useful if you were
+# deploying the binaries in a custom fuzzer deployment system.
+
+import sys
+import os
+import zipfile
+import stat
+
+def main(args=None):
+ if args is None:
+ args = sys.argv
+
+ if len(args) != 2 and len(args) != 3:
+ print("Usage: %s corpus_dir <output_dir>" % (args[0]))
+ return 1
+
+ root_dir = args[1]
+
+ if len(args) == 3:
+ output_dir = args[2]
+ else:
+ output_dir = ''
+
+ if not os.access(root_dir, os.R_OK):
+ print("Error could not access directory '%s'" % (root_dir))
+ return 1
+
+ for corpus_dir in os.listdir(root_dir):
+ if corpus_dir == '.git':
+ continue
+ subdir = os.path.join(root_dir, corpus_dir)
+ if not stat.S_ISDIR(os.stat(subdir).st_mode):
+ continue
+
+ zipfile_path = os.path.join(output_dir, '%s.zip' % (corpus_dir))
+ zf = zipfile.ZipFile(zipfile_path, 'w', zipfile.ZIP_DEFLATED)
+ for f in os.listdir(subdir):
+ zf.write(os.path.join(subdir, f), f)
+ zf.close()
+
+ return 0
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/src/scripts/test_fuzzers.py b/src/scripts/test_fuzzers.py
new file mode 100755
index 000000000..0d473e00c
--- /dev/null
+++ b/src/scripts/test_fuzzers.py
@@ -0,0 +1,78 @@
+#!/usr/bin/python
+
+import sys
+import os
+import subprocess
+
+def main(args=None):
+ if args is None:
+ args = sys.argv
+
+ if len(args) != 3:
+ print("Usage: %s <corpus_dir> <fuzzers_dir>" % (args[0]))
+ return 1
+
+ corpus_dir = args[1]
+ fuzzer_dir = args[2]
+
+ if not os.access(corpus_dir, os.R_OK):
+ print("Error could not access corpus directory '%s'" % (corpus_dir))
+ return 1
+
+ if not os.access(fuzzer_dir, os.R_OK):
+ print("Error could not access fuzzers directory '%s'" % (fuzzer_dir))
+ return 1
+
+ fuzzers = set([])
+ for fuzzer in os.listdir(fuzzer_dir):
+ if fuzzer.endswith('.zip'):
+ continue
+ fuzzers.add(fuzzer)
+
+ corpii = set([])
+ for corpus in os.listdir(corpus_dir):
+ if corpus in ['.git', 'readme.txt']:
+ continue
+ corpii.add(corpus)
+
+ fuzzers_without_corpus = fuzzers - corpii
+ corpus_without_fuzzers = corpii - fuzzers
+
+ for f in sorted(list(fuzzers_without_corpus)):
+ print("Warning: Fuzzer %s has no corpus" % (f))
+ for c in sorted(list(corpus_without_fuzzers)):
+ print("Warning: Corpus %s has no fuzzer" % (c))
+
+ fuzzers_with_corpus = fuzzers & corpii
+
+ any_crashes = False
+
+ for f in sorted(list(fuzzers_with_corpus)):
+ fuzzer_bin = os.path.join(fuzzer_dir, f)
+ corpus_files = os.path.join(corpus_dir, f)
+ for corpus_file in sorted(list(os.listdir(corpus_files))):
+ corpus_fd = open(os.path.join(corpus_files, corpus_file), 'r')
+ fuzzer_proc = subprocess.Popen([fuzzer_bin], stdin=corpus_fd,
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
+ (stdout, stderr) = fuzzer_proc.communicate()
+ corpus_fd.close()
+
+ if fuzzer_proc.returncode != 0:
+ print("Fuzzer %s crashed with input %s returncode %d" % (f, corpus_file, fuzzer_proc.returncode))
+ any_crashes = True
+
+ if len(stdout) != 0:
+ stdout = stdout.decode('ascii')
+ print("Fuzzer %s produced stdout on input %s:\n%s" % (f, corpus_file, stdout))
+
+ if len(stderr) != 0:
+ stderr = stderr.decode('ascii')
+ print("Fuzzer %s produced stderr on input %s:\n%s" % (f, corpus_file, stderr))
+
+ if any_crashes:
+ return 2
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())