diff options
Diffstat (limited to 'src/fuzzer')
-rw-r--r-- | src/fuzzer/asn1.cpp | 24 | ||||
-rw-r--r-- | src/fuzzer/bn_sqr.cpp | 24 | ||||
-rw-r--r-- | src/fuzzer/cert.cpp | 21 | ||||
-rw-r--r-- | src/fuzzer/crl.cpp | 18 | ||||
-rw-r--r-- | src/fuzzer/divide.cpp | 29 | ||||
-rw-r--r-- | src/fuzzer/ecc_bp256.cpp | 16 | ||||
-rw-r--r-- | src/fuzzer/ecc_helper.h | 58 | ||||
-rw-r--r-- | src/fuzzer/ecc_p256.cpp | 15 | ||||
-rw-r--r-- | src/fuzzer/ecc_p384.cpp | 15 | ||||
-rw-r--r-- | src/fuzzer/ecc_p521.cpp | 15 | ||||
-rw-r--r-- | src/fuzzer/fuzzers.h | 95 | ||||
-rw-r--r-- | src/fuzzer/invert.cpp | 87 | ||||
-rw-r--r-- | src/fuzzer/ocsp.cpp | 17 | ||||
-rw-r--r-- | src/fuzzer/os2ecp.cpp | 44 | ||||
-rw-r--r-- | src/fuzzer/pkcs1.cpp | 82 | ||||
-rw-r--r-- | src/fuzzer/pkcs8.cpp | 19 | ||||
-rw-r--r-- | src/fuzzer/pow_mod.cpp | 70 | ||||
-rw-r--r-- | src/fuzzer/redc_helper.h | 33 | ||||
-rw-r--r-- | src/fuzzer/redc_p192.cpp | 26 | ||||
-rw-r--r-- | src/fuzzer/redc_p224.cpp | 23 | ||||
-rw-r--r-- | src/fuzzer/redc_p256.cpp | 26 | ||||
-rw-r--r-- | src/fuzzer/redc_p384.cpp | 26 | ||||
-rw-r--r-- | src/fuzzer/redc_p521.cpp | 26 | ||||
-rw-r--r-- | src/fuzzer/ressol.cpp | 45 | ||||
-rw-r--r-- | src/fuzzer/tls_client.cpp | 57 | ||||
-rw-r--r-- | src/fuzzer/tls_client_hello.cpp | 18 | ||||
-rw-r--r-- | src/fuzzer/tls_server.cpp | 153 |
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) + { + } + } |