aboutsummaryrefslogtreecommitdiffstats
path: root/src/fuzzer
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2017-08-29 07:01:53 -0400
committerJack Lloyd <[email protected]>2017-08-29 07:01:53 -0400
commit922d3dcb678fa9ff9a54b9a920e530fe753da384 (patch)
tree3b7bbdc56376fd01a16c181895dd7c231a288d82 /src/fuzzer
parentd3cc9179a72cebddf2057256ab8a4d421b202b21 (diff)
parent4a64e42c3985ae7d460cf52d3e38a13b6b562572 (diff)
Merge GH #1158 Add build mode for fuzzer tests
Diffstat (limited to 'src/fuzzer')
-rw-r--r--src/fuzzer/asn1.cpp24
-rw-r--r--src/fuzzer/bn_sqr.cpp24
-rw-r--r--src/fuzzer/cert.cpp21
-rw-r--r--src/fuzzer/crl.cpp18
-rw-r--r--src/fuzzer/divide.cpp29
-rw-r--r--src/fuzzer/ecc_bp256.cpp16
-rw-r--r--src/fuzzer/ecc_helper.h58
-rw-r--r--src/fuzzer/ecc_p256.cpp15
-rw-r--r--src/fuzzer/ecc_p384.cpp15
-rw-r--r--src/fuzzer/ecc_p521.cpp15
-rw-r--r--src/fuzzer/fuzzers.h95
-rw-r--r--src/fuzzer/invert.cpp87
-rw-r--r--src/fuzzer/ocsp.cpp17
-rw-r--r--src/fuzzer/os2ecp.cpp44
-rw-r--r--src/fuzzer/pkcs1.cpp82
-rw-r--r--src/fuzzer/pkcs8.cpp19
-rw-r--r--src/fuzzer/pow_mod.cpp70
-rw-r--r--src/fuzzer/redc_helper.h33
-rw-r--r--src/fuzzer/redc_p192.cpp26
-rw-r--r--src/fuzzer/redc_p224.cpp23
-rw-r--r--src/fuzzer/redc_p256.cpp26
-rw-r--r--src/fuzzer/redc_p384.cpp26
-rw-r--r--src/fuzzer/redc_p521.cpp26
-rw-r--r--src/fuzzer/ressol.cpp45
-rw-r--r--src/fuzzer/tls_client.cpp57
-rw-r--r--src/fuzzer/tls_client_hello.cpp18
-rw-r--r--src/fuzzer/tls_server.cpp153
27 files changed, 1082 insertions, 0 deletions
diff --git a/src/fuzzer/asn1.cpp b/src/fuzzer/asn1.cpp
new file mode 100644
index 000000000..b0ea553e5
--- /dev/null
+++ b/src/fuzzer/asn1.cpp
@@ -0,0 +1,24 @@
+/*
+* (C) 2016,2017 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include "fuzzers.h"
+#include <botan/ber_dec.h>
+
+void fuzz(const uint8_t in[], size_t len)
+ {
+ try
+ {
+ Botan::DataSource_Memory input(in, len);
+ Botan::BER_Decoder dec(input);
+
+ while(dec.more_items())
+ {
+ Botan::BER_Object obj;
+ dec.get_next(obj);
+ }
+ }
+ catch(Botan::Exception& e) { }
+ }
diff --git a/src/fuzzer/bn_sqr.cpp b/src/fuzzer/bn_sqr.cpp
new file mode 100644
index 000000000..f507c4a79
--- /dev/null
+++ b/src/fuzzer/bn_sqr.cpp
@@ -0,0 +1,24 @@
+/*
+* (C) 2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include "fuzzers.h"
+
+#include <botan/bigint.h>
+#include <botan/numthry.h>
+
+void fuzz(const uint8_t in[], size_t len)
+ {
+ if(len > 8192/8)
+ return;
+
+ Botan::BigInt x = Botan::BigInt::decode(in, len);
+
+ Botan::BigInt x_sqr = square(x);
+ Botan::BigInt x_mul = x * x;
+
+ FUZZER_ASSERT_EQUAL(x_sqr, x_mul);
+ }
+
diff --git a/src/fuzzer/cert.cpp b/src/fuzzer/cert.cpp
new file mode 100644
index 000000000..3b40020df
--- /dev/null
+++ b/src/fuzzer/cert.cpp
@@ -0,0 +1,21 @@
+/*
+* (C) 2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include "fuzzers.h"
+#include <botan/x509cert.h>
+
+void fuzz(const uint8_t in[], size_t len)
+ {
+ if(len > max_fuzzer_input_size)
+ return;
+
+ try
+ {
+ Botan::DataSource_Memory input(in, len);
+ Botan::X509_Certificate cert(input);
+ }
+ catch(Botan::Exception& e) { }
+ }
diff --git a/src/fuzzer/crl.cpp b/src/fuzzer/crl.cpp
new file mode 100644
index 000000000..63699b9b3
--- /dev/null
+++ b/src/fuzzer/crl.cpp
@@ -0,0 +1,18 @@
+/*
+* (C) 2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include "fuzzers.h"
+#include <botan/x509_crl.h>
+
+void fuzz(const uint8_t in[], size_t len)
+ {
+ try
+ {
+ Botan::DataSource_Memory input(in, len);
+ Botan::X509_CRL crl(input);
+ }
+ catch(Botan::Exception& e) {}
+ }
diff --git a/src/fuzzer/divide.cpp b/src/fuzzer/divide.cpp
new file mode 100644
index 000000000..01ec14e28
--- /dev/null
+++ b/src/fuzzer/divide.cpp
@@ -0,0 +1,29 @@
+/*
+* (C) 2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+#include "fuzzers.h"
+#include <botan/divide.h>
+
+void fuzz(const uint8_t in[], size_t len)
+ {
+ if(len % 2 == 1 || len > 2*4096/8)
+ return;
+
+ 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;
+
+ Botan::BigInt q, r;
+ Botan::divide(x, y, q, r);
+
+ FUZZER_ASSERT_TRUE(r < y);
+
+ Botan::BigInt z = q*y + r;
+
+ FUZZER_ASSERT_EQUAL(z, x);
+ }
+
diff --git a/src/fuzzer/ecc_bp256.cpp b/src/fuzzer/ecc_bp256.cpp
new file mode 100644
index 000000000..4c1186f06
--- /dev/null
+++ b/src/fuzzer/ecc_bp256.cpp
@@ -0,0 +1,16 @@
+/*
+* (C) 2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+#include "fuzzers.h"
+#include "ecc_helper.h"
+
+void fuzz(const uint8_t in[], size_t len)
+ {
+ if(len > 2*256/8)
+ return;
+
+ static Botan::EC_Group bp256("brainpool256r1");
+ return check_ecc_math(bp256, in, len);
+ }
diff --git a/src/fuzzer/ecc_helper.h b/src/fuzzer/ecc_helper.h
new file mode 100644
index 000000000..c9b3a6604
--- /dev/null
+++ b/src/fuzzer/ecc_helper.h
@@ -0,0 +1,58 @@
+/*
+* (C) 2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef ECC_HELPERS_H__
+#define ECC_HELPERS_H__
+
+#include "fuzzers.h"
+#include <botan/curve_gfp.h>
+#include <botan/ec_group.h>
+#include <botan/reducer.h>
+
+namespace {
+
+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 Botan::EC_Group& group,
+ const uint8_t in[], size_t len)
+ {
+ // These depend only on the group, which is also static
+ static const Botan::PointGFp base_point = group.get_base_point();
+ static Botan::Blinded_Point_Multiply blind(base_point, group.get_order(), 4);
+
+ const size_t hlen = len / 2;
+ 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;
+
+ const Botan::PointGFp P = base_point * a;
+ const Botan::PointGFp Q = base_point * b;
+ const Botan::PointGFp R = base_point * c;
+
+ const Botan::PointGFp A1 = P + Q;
+ const Botan::PointGFp A2 = Q + P;
+
+ FUZZER_ASSERT_EQUAL(A1, A2);
+
+ const Botan::PointGFp P1 = blind.blinded_multiply(a, fuzzer_rng());
+ const Botan::PointGFp Q1 = blind.blinded_multiply(b, fuzzer_rng());
+ const Botan::PointGFp R1 = blind.blinded_multiply(c, fuzzer_rng());
+
+ const Botan::PointGFp S1 = P1 + Q1;
+ const Botan::PointGFp S2 = Q1 + P1;
+
+ FUZZER_ASSERT_EQUAL(S1, S2);
+ FUZZER_ASSERT_EQUAL(S1, A1);
+ }
+
+}
+
+#endif
diff --git a/src/fuzzer/ecc_p256.cpp b/src/fuzzer/ecc_p256.cpp
new file mode 100644
index 000000000..c00be71b6
--- /dev/null
+++ b/src/fuzzer/ecc_p256.cpp
@@ -0,0 +1,15 @@
+/*
+* (C) 2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+#include "fuzzers.h"
+#include "ecc_helper.h"
+
+void fuzz(const uint8_t in[], size_t len)
+ {
+ if(len > 2*256/8)
+ return;
+ static Botan::EC_Group p256("secp256r1");
+ return check_ecc_math(p256, in, len);
+ }
diff --git a/src/fuzzer/ecc_p384.cpp b/src/fuzzer/ecc_p384.cpp
new file mode 100644
index 000000000..1b58da958
--- /dev/null
+++ b/src/fuzzer/ecc_p384.cpp
@@ -0,0 +1,15 @@
+/*
+* (C) 2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+#include "fuzzers.h"
+#include "ecc_helper.h"
+
+void fuzz(const uint8_t in[], size_t len)
+ {
+ if(len > 2*384/8)
+ return;
+ static Botan::EC_Group p384("secp384r1");
+ return check_ecc_math(p384, in, len);
+ }
diff --git a/src/fuzzer/ecc_p521.cpp b/src/fuzzer/ecc_p521.cpp
new file mode 100644
index 000000000..3b9ed2d5c
--- /dev/null
+++ b/src/fuzzer/ecc_p521.cpp
@@ -0,0 +1,15 @@
+/*
+* (C) 2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+#include "fuzzers.h"
+#include "ecc_helper.h"
+
+void fuzz(const uint8_t in[], size_t len)
+ {
+ if(len > 2*(521+7)/8)
+ return;
+ static Botan::EC_Group p521("secp521r1");
+ return check_ecc_math(p521, in, len);
+ }
diff --git a/src/fuzzer/fuzzers.h b/src/fuzzer/fuzzers.h
new file mode 100644
index 000000000..2f1b1346d
--- /dev/null
+++ b/src/fuzzer/fuzzers.h
@@ -0,0 +1,95 @@
+/*
+* (C) 2015,2016,2017 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_FUZZER_DRIVER_H__
+#define BOTAN_FUZZER_DRIVER_H__
+
+#include <stdint.h>
+#include <stdlib.h> // for setenv
+#include <iostream>
+#include <vector>
+#include <botan/exceptn.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
+
+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 *, char ***)
+ {
+ /*
+ * This disables the mlock pool, as overwrites within the pool are
+ * opaque to ASan or other instrumentation.
+ */
+ ::setenv("BOTAN_MLOCK_POOL_SIZE", "0", 1);
+ return 0;
+ }
+
+// Called by main() in libFuzzer or in main for AFL below
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t in[], size_t len)
+ {
+ if(len <= max_fuzzer_input_size)
+ {
+ fuzz(in, len);
+ }
+ return 0;
+ }
+
+// Some helpers for the fuzzer jigs
+
+inline Botan::RandomNumberGenerator& fuzzer_rng()
+ {
+ static Botan::ChaCha_RNG rng(Botan::secure_vector<uint8_t>(32));
+ return rng;
+ }
+
+#define FUZZER_ASSERT_EQUAL(x, y) do { \
+ if(x != y) { \
+ std::cerr << #x << " = " << x << " !=\n" << #y << " = " << y \
+ << " at " << __LINE__ << ":" << __FILE__ << std::endl; \
+ abort(); \
+} } while(0)
+
+#define FUZZER_ASSERT_TRUE(e) \
+ do { \
+ if(!(e)) { \
+ std::cerr << "Expression " << #e << " was false at " \
+ << __LINE__ << ":" << __FILE__ << std::endl; \
+ 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/fuzzer/invert.cpp b/src/fuzzer/invert.cpp
new file mode 100644
index 000000000..08e8229b8
--- /dev/null
+++ b/src/fuzzer/invert.cpp
@@ -0,0 +1,87 @@
+/*
+* (C) 2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+#include "fuzzers.h"
+#include <botan/numthry.h>
+
+namespace {
+
+Botan::BigInt inverse_mod_ref(const Botan::BigInt& n, const Botan::BigInt& mod)
+ {
+ if(n == 0)
+ return 0;
+
+ Botan::BigInt u = mod, v = n;
+ Botan::BigInt B = 0, D = 1;
+
+ while(u.is_nonzero())
+ {
+ const size_t u_zero_bits = low_zero_bits(u);
+ u >>= u_zero_bits;
+ for(size_t i = 0; i != u_zero_bits; ++i)
+ {
+ //B.cond_sub(B.is_odd(), mod);
+ if(B.is_odd())
+ { B -= mod; }
+ B >>= 1;
+ }
+
+ const size_t v_zero_bits = low_zero_bits(v);
+ v >>= v_zero_bits;
+ for(size_t i = 0; i != v_zero_bits; ++i)
+ {
+ if(D.is_odd())
+ { D -= mod; }
+ D >>= 1;
+ }
+
+ if(u >= v) { u -= v; B -= D; }
+ else { v -= u; D -= B; }
+ }
+
+ if(v != 1)
+ return 0; // no modular inverse
+
+ while(D.is_negative()) D += mod;
+ while(D >= mod) D -= mod;
+
+ return D;
+ }
+
+}
+
+void fuzz(const uint8_t in[], size_t len)
+ {
+ if(len % 2 == 1 || len > 2*4096/8)
+ return;
+
+ 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;
+
+ 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)
+ {
+ std::cout << "X = " << x << "\n";
+ std::cout << "P = " << mod << "\n";
+ std::cout << "GCD = " << gcd(x, mod) << "\n";
+ std::cout << "Ref = " << ref << "\n";
+ std::cout << "CT = " << ct << "\n";
+ //std::cout << "Mon = " << mon << "\n";
+
+ std::cout << "RefCheck = " << (ref*ref)%mod << "\n";
+ std::cout << "CTCheck = " << (ct*ct)%mod << "\n";
+ //std::cout << "MonCheck = " << (mon*mon)%mod << "\n";
+ abort();
+ }
+ }
+
diff --git a/src/fuzzer/ocsp.cpp b/src/fuzzer/ocsp.cpp
new file mode 100644
index 000000000..0db265b8d
--- /dev/null
+++ b/src/fuzzer/ocsp.cpp
@@ -0,0 +1,17 @@
+/*
+* (C) 2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include "fuzzers.h"
+#include <botan/ocsp.h>
+
+void fuzz(const uint8_t in[], size_t len)
+ {
+ try
+ {
+ Botan::OCSP::Response response(in, len);
+ }
+ catch(Botan::Exception& e) { }
+ }
diff --git a/src/fuzzer/os2ecp.cpp b/src/fuzzer/os2ecp.cpp
new file mode 100644
index 000000000..dba6dbdfe
--- /dev/null
+++ b/src/fuzzer/os2ecp.cpp
@@ -0,0 +1,44 @@
+/*
+* (C) 2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+#include "fuzzers.h"
+#include <botan/ec_group.h>
+#include <botan/point_gfp.h>
+
+namespace {
+
+void check_os2ecp(const Botan::EC_Group& group, const uint8_t in[], size_t len)
+ {
+ try
+ {
+ 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 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);
+ check_os2ecp(p256, in, len);
+ check_os2ecp(p384, in, len);
+ check_os2ecp(p521, in, len);
+ check_os2ecp(p521, in, len);
+ check_os2ecp(bp256, in, len);
+ check_os2ecp(bp512, in, len);
+ }
diff --git a/src/fuzzer/pkcs1.cpp b/src/fuzzer/pkcs1.cpp
new file mode 100644
index 000000000..a0323d2b2
--- /dev/null
+++ b/src/fuzzer/pkcs1.cpp
@@ -0,0 +1,82 @@
+/*
+* (C) 2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+#include "fuzzers.h"
+
+#include <botan/eme_pkcs.h>
+#include <botan/hex.h>
+
+namespace {
+
+std::vector<uint8_t> simple_pkcs1_unpad(const uint8_t in[], size_t len)
+ {
+ if(len < 10)
+ throw Botan::Decoding_Error("bad len");
+
+ if(in[0] != 0 || in[1] != 2)
+ throw Botan::Decoding_Error("bad header field");
+
+ for(size_t i = 2; i < len; ++i)
+ {
+ if(in[i] == 0)
+ {
+ if(i < 10) // at least 8 padding bytes required
+ throw Botan::Decoding_Error("insufficient padding bytes");
+ 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 Botan::EME_PKCS1v15 pkcs1;
+
+ Botan::secure_vector<uint8_t> lib_result;
+ std::vector<uint8_t> ref_result;
+ bool lib_rejected = false, ref_rejected = false;
+
+ try
+ {
+ 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;
+ else if(valid_mask == 0xFF)
+ lib_rejected = false;
+ else
+ abort();
+ }
+ catch(Botan::Decoding_Error&) { lib_rejected = true; }
+
+ try
+ {
+ ref_result = simple_pkcs1_unpad(in, len);
+ }
+ catch(Botan::Decoding_Error& e) { ref_rejected = true; }
+
+ if(lib_rejected == ref_rejected)
+ {
+ return; // ok, they agree
+ }
+
+ // otherwise: incorrect result, log info and crash
+ if(lib_rejected == true && ref_rejected == false)
+ {
+ std::cerr << "Library rejected input accepted by ref\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 " << Botan::hex_encode(lib_result) << "\n";
+ }
+
+ abort();
+ }
diff --git a/src/fuzzer/pkcs8.cpp b/src/fuzzer/pkcs8.cpp
new file mode 100644
index 000000000..ad43d6f3e
--- /dev/null
+++ b/src/fuzzer/pkcs8.cpp
@@ -0,0 +1,19 @@
+/*
+* (C) 2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+#include "fuzzers.h"
+
+#include <botan/pkcs8.h>
+
+void fuzz(const uint8_t in[], size_t len)
+ {
+ try
+ {
+ 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/fuzzer/pow_mod.cpp b/src/fuzzer/pow_mod.cpp
new file mode 100644
index 000000000..2244c2004
--- /dev/null
+++ b/src/fuzzer/pow_mod.cpp
@@ -0,0 +1,70 @@
+/*
+* (C) 2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include "fuzzers.h"
+#include <botan/numthry.h>
+#include <botan/reducer.h>
+#include <botan/pow_mod.h>
+
+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)
+ {
+ if(p == 1)
+ return 0;
+ return 1;
+ }
+
+ Botan::BigInt y = 1;
+
+ while(n > 1)
+ {
+ if(n.is_odd())
+ {
+ y = mod_p.multiply(x, y);
+ }
+ x = mod_p.square(x);
+ n >>= 1;
+ }
+ return mod_p.multiply(x, y);
+ }
+
+}
+
+void fuzz(const uint8_t in[], size_t len)
+ {
+ static const size_t p_bits = 1024;
+ 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 Botan::BigInt g = Botan::BigInt::decode(in, len / 2);
+ const Botan::BigInt x = Botan::BigInt::decode(in + len / 2, len / 2);
+
+ 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)
+ {
+ std::cout << "G = " << g << "\n"
+ << "X = " << x << "\n"
+ << "P = " << p << "\n"
+ << "Z = " << z << "\n"
+ << "R = " << ref << "\n";
+ abort();
+ }
+ }
+ catch(Botan::Exception& e) {}
+ }
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/fuzzer/redc_p192.cpp b/src/fuzzer/redc_p192.cpp
new file mode 100644
index 000000000..e1f7c753f
--- /dev/null
+++ b/src/fuzzer/redc_p192.cpp
@@ -0,0 +1,26 @@
+/*
+* (C) 2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include "fuzzers.h"
+#include "redc_helper.h"
+#include <botan/curve_nistp.h>
+
+void fuzz(const uint8_t in[], size_t len)
+ {
+ if(len > 2*192/8)
+ return;
+
+ 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);
+
+ if(x < prime_2)
+ {
+ check_redc(Botan::redc_p192, prime_redc, prime, x);
+ }
+ }
diff --git a/src/fuzzer/redc_p224.cpp b/src/fuzzer/redc_p224.cpp
new file mode 100644
index 000000000..a8a4d5d72
--- /dev/null
+++ b/src/fuzzer/redc_p224.cpp
@@ -0,0 +1,23 @@
+/*
+* (C) 2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include "fuzzers.h"
+#include "redc_helper.h"
+#include <botan/curve_nistp.h>
+
+void fuzz(const uint8_t in[], size_t len)
+ {
+ 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);
+
+ if(x < prime_2)
+ {
+ check_redc(Botan::redc_p224, prime_redc, prime, x);
+ }
+ }
diff --git a/src/fuzzer/redc_p256.cpp b/src/fuzzer/redc_p256.cpp
new file mode 100644
index 000000000..b8d78e7bb
--- /dev/null
+++ b/src/fuzzer/redc_p256.cpp
@@ -0,0 +1,26 @@
+/*
+* (C) 2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include "fuzzers.h"
+#include "redc_helper.h"
+#include <botan/curve_nistp.h>
+
+void fuzz(const uint8_t in[], size_t len)
+ {
+ if(len > 2*256/8)
+ return;
+
+ 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);
+
+ if(x < prime_2)
+ {
+ check_redc(Botan::redc_p256, prime_redc, prime, x);
+ }
+ }
diff --git a/src/fuzzer/redc_p384.cpp b/src/fuzzer/redc_p384.cpp
new file mode 100644
index 000000000..35e3ccfee
--- /dev/null
+++ b/src/fuzzer/redc_p384.cpp
@@ -0,0 +1,26 @@
+/*
+* (C) 2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include "fuzzers.h"
+#include "redc_helper.h"
+#include <botan/curve_nistp.h>
+
+void fuzz(const uint8_t in[], size_t len)
+ {
+ if(len > 2*384/8)
+ return;
+
+ 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);
+
+ if(x < prime_2)
+ {
+ check_redc(Botan::redc_p384, prime_redc, prime, x);
+ }
+ }
diff --git a/src/fuzzer/redc_p521.cpp b/src/fuzzer/redc_p521.cpp
new file mode 100644
index 000000000..c6c5d262b
--- /dev/null
+++ b/src/fuzzer/redc_p521.cpp
@@ -0,0 +1,26 @@
+/*
+* (C) 2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include "fuzzers.h"
+#include "redc_helper.h"
+#include <botan/curve_nistp.h>
+
+void fuzz(const uint8_t in[], size_t len)
+ {
+ if(len > 2*(521+7)/8)
+ return;
+
+ 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);
+
+ if(x < prime_2)
+ {
+ check_redc(Botan::redc_p521, prime_redc, prime, x);
+ }
+ }
diff --git a/src/fuzzer/ressol.cpp b/src/fuzzer/ressol.cpp
new file mode 100644
index 000000000..17ba88b8b
--- /dev/null
+++ b/src/fuzzer/ressol.cpp
@@ -0,0 +1,45 @@
+/*
+* (C) 2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include "fuzzers.h"
+#include <botan/numthry.h>
+#include <botan/reducer.h>
+
+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 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 Botan::BigInt a = Botan::BigInt::decode(in, len);
+ Botan::BigInt a_sqrt = Botan::ressol(a, p);
+
+ if(a_sqrt > 0)
+ {
+ const Botan::BigInt a_redc = mod_p.reduce(a);
+ const Botan::BigInt z = mod_p.square(a_sqrt);
+
+ if(z != a_redc)
+ {
+ std::cout << "A = " << a << "\n";
+ std::cout << "P = " << p << "\n";
+ std::cout << "R = " << a_sqrt << "\n";
+ std::cout << "Z = " << z << "\n";
+ abort();
+ }
+ }
+ }
+ catch(Botan::Exception& e) {}
+
+ return;
+ }
+
diff --git a/src/fuzzer/tls_client.cpp b/src/fuzzer/tls_client.cpp
new file mode 100644
index 000000000..197e97928
--- /dev/null
+++ b/src/fuzzer/tls_client.cpp
@@ -0,0 +1,57 @@
+/*
+* (C) 2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include "fuzzers.h"
+#include <botan/tls_client.h>
+
+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"; }
+ Botan::SymmetricKey psk(const std::string&, const std::string&, const std::string&) override
+ {
+ return Botan::SymmetricKey("AABBCCDDEEFF00112233445566778899");
+ }
+ };
+
+void fuzz(const uint8_t in[], size_t len)
+ {
+ if(len == 0)
+ return;
+
+ auto dev_null = [](const uint8_t[], size_t) {};
+
+ auto ignore_alerts = [](Botan::TLS::Alert, const uint8_t[], size_t) {};
+ auto ignore_hs = [](const Botan::TLS::Session&) { abort(); return true; };
+
+ 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;
+
+ Botan::TLS::Client client(dev_null,
+ dev_null,
+ ignore_alerts,
+ ignore_hs,
+ session_manager,
+ creds,
+ policy,
+ fuzzer_rng(),
+ info,
+ client_offer);
+
+ try
+ {
+ client.received_data(in, len);
+ }
+ catch(std::exception& e)
+ {
+ }
+
+ }
+
diff --git a/src/fuzzer/tls_client_hello.cpp b/src/fuzzer/tls_client_hello.cpp
new file mode 100644
index 000000000..28c77c9b6
--- /dev/null
+++ b/src/fuzzer/tls_client_hello.cpp
@@ -0,0 +1,18 @@
+/*
+* (C) 2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include "fuzzers.h"
+#include <botan/tls_messages.h>
+
+void fuzz(const uint8_t in[], size_t len)
+ {
+ try
+ {
+ std::vector<uint8_t> v(in, in + len);
+ Botan::TLS::Client_Hello ch(v);
+ }
+ catch(Botan::Exception& e) {}
+ }
diff --git a/src/fuzzer/tls_server.cpp b/src/fuzzer/tls_server.cpp
new file mode 100644
index 000000000..54586595f
--- /dev/null
+++ b/src/fuzzer/tls_server.cpp
@@ -0,0 +1,153 @@
+/*
+* (C) 2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include "fuzzers.h"
+#include <botan/tls_server.h>
+
+const char* fixed_rsa_key =
+ "-----BEGIN PRIVATE KEY-----\n"
+ "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCe6qqpMQVJ7zCJ\n"
+ "oSnpxia0yO6M7Ie3FGqPcd0DzueC+kWPvuHQ+PpP5vfO6qqRaDVII37PFX5NUZQm\n"
+ "GK/rAm7spjIHTCMgqSZ8pN13LU8m1gDwIdu9al16LXN9zZjB67uLlFn2trtLi234\n"
+ "i0cnyeF8IC0cz7tgCOzMSVEBcqJjkdgGrZ3WUgOXecVm2lXVrYlEiaSxFp4VOE9k\n"
+ "RFeVrELCjmNtc4hRd1yJsF+vObCtvyqGYQE1Qcb0MVSQDBHMkiUVmO6zuW7td5ef\n"
+ "O/1OyntQJGyVa+SnWbkSLCybta2J7MreHENrF5GA0K1KL140SNRHeWifRMuNQua7\n"
+ "qmKXMBTFAgMBAAECggEAIk3fxyQI0zvpy1vZ01ft1QqmzA7nAPNMSWi33/GS8iga\n"
+ "SfxXfKeySPs/tQ/dAARxs//NiOBH4mLgyxR7LQzaawU5OXALCSraXv+ruuUx990s\n"
+ "WKnGaG4EfbJAAwEVn47Gbkv425P4fEc91vAhzQn8PbIoatbAyOtESpjs/pYDTeC/\n"
+ "mnJId8gqO90cqyRECEMjk9sQ8iEjWPlik4ayGlUVbeeMu6/pJ9F8IZEgkLZiNDAB\n"
+ "4anmOFaT7EmqUjI4IlcaqfbbXyDXlvWUYukidEss+CNvPuqbQHBDnpFVvBxdDR2N\n"
+ "Uj2D5Xd5blcIe2/+1IVRnznjoQ5zvutzb7ThBmMehQKBgQDOITKG0ht2kXLxjVoR\n"
+ "r/pVpx+f3hs3H7wE0+vrLHoQgkVjpMWXQ47YuZTT9rCOOYNI2cMoH2D27t1j78/B\n"
+ "9kGYABUVpvQQ+6amqJDI1eYI6e68TPueEDjeALfSCdmPNiI3lZZrCIK9XLpkoy8K\n"
+ "tGYBRRJ+JJxjj1zPXj9SGshPgwKBgQDFXUtoxY3mCStH3+0b1qxGG9r1L5goHEmd\n"
+ "Am8WBYDheNpL0VqPNzouhuM/ZWMGyyAs/py6aLATe+qhR1uX5vn7LVZwjCSONZ4j\n"
+ "7ieEEUh1BHetPI1oI5PxgokRYfVuckotqVseanI/536Er3Yf2FXNQ1/ceVp9WykX\n"
+ "3mYTKMhQFwKBgQDKakcXpZNaZ5IcKdZcsBZ/rdGcR5sqEnursf9lvRNQytwg8Vkn\n"
+ "JSxNHlBLpV/TCh8lltHRwJ6TXhUBYij+KzhWbx5FWOErHDOWTMmArqtp7W6GcoJT\n"
+ "wVJWjxXzp8CApYQMWVSQXpckJL7UvHohZO0WKiHyxTjde5aD++TqV2qEyQKBgBbD\n"
+ "jvoTpy08K4DLxCZs2Uvw1I1pIuylbpwsdrGciuP2s38BM6fHH+/T4Qwj3osfDKQD\n"
+ "7gHWJ1Dn/wUBHQBlRLoC3bB3iZPZfVb5lhc2gxv0GvWhQVIcoGi/vJ2DpfJKPmIL\n"
+ "4ZWdg3X5dm9JaZ98rVDSj5D3ckd5J0E4hp95GbmbAoGBAJJHM4O9lx60tIjw9Sf/\n"
+ "QmKWyUk0NLnt8DcgRMW7fVxtzPNDy9DBKGIkDdWZ2s+ForICA3C9WSxBC1EOEHGG\n"
+ "xkg2xKt66CeutGroP6M191mHQrRClt1VbEYzQFX21BCk5kig9i/BURyoTHtFiV+t\n"
+ "kbf4VLg8Vk9u/R3RU1HsYWhe\n"
+ "-----END PRIVATE KEY-----\n";
+
+const char* fixed_rsa_cert =
+ "-----BEGIN CERTIFICATE-----\n"
+ "MIIDUDCCAjgCCQD7pIb1ZsoafjANBgkqhkiG9w0BAQsFADBqMQswCQYDVQQGEwJW\n"
+ "VDEQMA4GA1UECAwHVmVybW9udDEWMBQGA1UEBwwNVGhlIEludGVybmV0czEUMBIG\n"
+ "A1UECgwLTWFuZ29zIFIgVXMxGzAZBgNVBAMMEnNlcnZlci5leGFtcGxlLmNvbTAe\n"
+ "Fw0xNjAxMDYxNzQ3MjNaFw0yNjAxMDMxNzQ3MjNaMGoxCzAJBgNVBAYTAlZUMRAw\n"
+ "DgYDVQQIDAdWZXJtb250MRYwFAYDVQQHDA1UaGUgSW50ZXJuZXRzMRQwEgYDVQQK\n"
+ "DAtNYW5nb3MgUiBVczEbMBkGA1UEAwwSc2VydmVyLmV4YW1wbGUuY29tMIIBIjAN\n"
+ "BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnuqqqTEFSe8wiaEp6cYmtMjujOyH\n"
+ "txRqj3HdA87ngvpFj77h0Pj6T+b3zuqqkWg1SCN+zxV+TVGUJhiv6wJu7KYyB0wj\n"
+ "IKkmfKTddy1PJtYA8CHbvWpdei1zfc2Yweu7i5RZ9ra7S4tt+ItHJ8nhfCAtHM+7\n"
+ "YAjszElRAXKiY5HYBq2d1lIDl3nFZtpV1a2JRImksRaeFThPZERXlaxCwo5jbXOI\n"
+ "UXdcibBfrzmwrb8qhmEBNUHG9DFUkAwRzJIlFZjus7lu7XeXnzv9Tsp7UCRslWvk\n"
+ "p1m5Eiwsm7WtiezK3hxDaxeRgNCtSi9eNEjUR3lon0TLjULmu6pilzAUxQIDAQAB\n"
+ "MA0GCSqGSIb3DQEBCwUAA4IBAQA1eZGc/4V7z/E/6eG0hVkzoAZeuTcSP7WqBSx+\n"
+ "OP2yh0163UYjoa6nehmkKYQQ9PbYPZGzIcl+dBFyYzy6jcp0NdtzpWnTFrjl4rMq\n"
+ "akcQ1D0LTYjJXVP9G/vF/SvatOFeVTnQmLlLt/a8ZtRUINqejeZZPzH8ifzFW6tu\n"
+ "mlhTVIEKyPHpxClh5Y3ubw/mZYygekFTqMkTx3FwJxKU8J6rYGZxanWAODUIvCUo\n"
+ "Fxer1qC5Love3uWl3vXPLEZWZdORnExSRByzz2immBP2vX4zYZoeZRhTQ9ae1TIV\n"
+ "Dk02a/1AOJZdZReDbgXhlqaUx5pk/rzo4mDzvu5HSCeXmClz\n"
+ "-----END CERTIFICATE-----\n";
+
+class Fuzzer_TLS_Server_Creds : public Botan::Credentials_Manager
+ {
+ public:
+ Fuzzer_TLS_Server_Creds()
+ {
+ 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());
+ }
+
+ std::vector<Botan::X509_Certificate> cert_chain(
+ const std::vector<std::string>& algos,
+ const std::string& /*type*/,
+ const std::string& /*hostname*/) override
+ {
+ std::vector<Botan::X509_Certificate> v;
+
+ for(auto algo : algos)
+ {
+ if(algo == "RSA")
+ {
+ v.push_back(*m_rsa_cert);
+ break;
+ }
+ }
+
+ return v;
+ }
+
+ Botan::Private_Key* private_key_for(const Botan::X509_Certificate& /*cert*/,
+ const std::string& /*type*/,
+ const std::string& /*context*/) override
+ {
+ return m_rsa_key.get();
+ }
+
+ 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"; }
+ Botan::SymmetricKey psk(const std::string&, const std::string&, const std::string&) override
+ {
+ return Botan::SymmetricKey("AABBCCDDEEFF00112233445566778899");
+ }
+ private:
+ std::unique_ptr<Botan::X509_Certificate> m_rsa_cert;
+ std::unique_ptr<Botan::Private_Key> m_rsa_key;
+ };
+
+void fuzz(const uint8_t in[], size_t len)
+ {
+ if(len == 0)
+ return;
+
+ auto dev_null = [](const uint8_t[], size_t) {};
+
+ auto ignore_alerts = [](Botan::TLS::Alert, const uint8_t[], size_t) {};
+ auto ignore_hs = [](const Botan::TLS::Session&) { return true; };
+
+ 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 {
+ if(protos.size() > 1)
+ return protos[0];
+ else
+ return "fuzzed";
+ };
+
+ const bool is_datagram = (len % 2 == 0);
+
+ Botan::TLS::Server server(dev_null,
+ dev_null,
+ ignore_alerts,
+ ignore_hs,
+ session_manager,
+ creds,
+ policy,
+ fuzzer_rng(),
+ next_proto_fn,
+ is_datagram);
+
+ try
+ {
+ server.received_data(in, len);
+ }
+ catch(std::exception& e)
+ {
+ }
+ }