diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /comm/third_party/botan/src/fuzzer | |
parent | Initial commit. (diff) | |
download | thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'comm/third_party/botan/src/fuzzer')
33 files changed, 2017 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/fuzzer/asn1.cpp b/comm/third_party/botan/src/fuzzer/asn1.cpp new file mode 100644 index 0000000000..89073991d1 --- /dev/null +++ b/comm/third_party/botan/src/fuzzer/asn1.cpp @@ -0,0 +1,43 @@ +/* +* (C) 2016,2017 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include "fuzzers.h" +#include <botan/asn1_print.h> +#include <fstream> + +class ASN1_Parser final : public Botan::ASN1_Formatter + { + public: + ASN1_Parser() : Botan::ASN1_Formatter(true, 64) {} + + protected: + std::string format(Botan::ASN1_Tag, Botan::ASN1_Tag, size_t, size_t, + const std::string&) const override + { + return ""; + } + + std::string format_bin(Botan::ASN1_Tag, Botan::ASN1_Tag, + const std::vector<uint8_t>&) const override + { + return ""; + } + }; + +void fuzz(const uint8_t in[], size_t len) + { + try + { + /* + * Here we use an uninitialized ofstream so the fuzzer doesn't spend time + * on actual output formatting, no memory is allocated, etc. + */ + std::ofstream out; + ASN1_Parser printer; + printer.print_to_stream(out, in, len); + } + catch(Botan::Exception& e) { } + } diff --git a/comm/third_party/botan/src/fuzzer/barrett.cpp b/comm/third_party/botan/src/fuzzer/barrett.cpp new file mode 100644 index 0000000000..ebc6001971 --- /dev/null +++ b/comm/third_party/botan/src/fuzzer/barrett.cpp @@ -0,0 +1,49 @@ +/* +* (C) 2018,2020 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/divide.h> + +void fuzz(const uint8_t in[], size_t len) + { + static const size_t max_bits = 4096; + + if(len <= 4) + return; + + if(len > 2*(max_bits/8)) + return; + + const size_t x_len = 2 * ((len + 2) / 3); + + Botan::BigInt x = Botan::BigInt::decode(in, x_len); + const Botan::BigInt p = Botan::BigInt::decode(in + x_len, len - x_len); + + if(p.is_zero()) + return; + + const size_t x_bits = x.bits(); + if(x_bits % 8 == 0 && x_bits / 8 == x_len) + x.flip_sign(); + + const Botan::BigInt ref = x % p; + + const Botan::Modular_Reducer mod_p(p); + const Botan::BigInt z = mod_p.reduce(x); + + const Botan::BigInt ct = ct_modulo(x, p); + + if(ref != z || ref != ct) + { + FUZZER_WRITE_AND_CRASH("X = " << x << "\n" + << "P = " << p << "\n" + << "Barrett = " << z << "\n" + << "Ct = " << ct << "\n" + << "Ref = " << ref << "\n"); + } + } diff --git a/comm/third_party/botan/src/fuzzer/bn_cmp.cpp b/comm/third_party/botan/src/fuzzer/bn_cmp.cpp new file mode 100644 index 0000000000..48c25f3247 --- /dev/null +++ b/comm/third_party/botan/src/fuzzer/bn_cmp.cpp @@ -0,0 +1,74 @@ +/* +* (C) 2021 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include "fuzzers.h" + +#include <botan/bigint.h> + +void fuzz(const uint8_t in[], size_t len) + { + const size_t max_bits = 512; + + if(len < 3 || len > 1 + 2*(max_bits/8)) + return; + + const uint8_t signs = in[0]; + const size_t x_len = (len - 1) / 2; + + Botan::BigInt x = Botan::BigInt::decode(in + 1, x_len); + Botan::BigInt y = Botan::BigInt::decode(in + 1 + x_len, len - x_len - 1); + + if(signs & 1) + x.flip_sign(); + if(signs & 2) + y.flip_sign(); + + const Botan::BigInt d1 = x - y; + const Botan::BigInt d2 = y - x; + + FUZZER_ASSERT_TRUE(d1.cmp(d2, false) == 0); + + const bool is_eq = (x == y); + const bool is_lt = (x < y); + const bool is_gt = (x > y); + const bool is_lte = (x <= y); + const bool is_gte = (x >= y); + + if(is_eq) + { + FUZZER_ASSERT_TRUE(d1.is_zero()); + FUZZER_ASSERT_TRUE(d2.is_zero()); + } + + if(is_lte) + { + FUZZER_ASSERT_TRUE(is_lt || is_eq); + } + + if(is_gte) + { + FUZZER_ASSERT_TRUE(is_gt || is_eq); + } + + if(is_lt) + { + FUZZER_ASSERT_TRUE(!is_gt); + FUZZER_ASSERT_TRUE(d1.is_nonzero()); + FUZZER_ASSERT_TRUE(d2.is_nonzero()); + FUZZER_ASSERT_TRUE(d1.is_negative()); + FUZZER_ASSERT_TRUE(d2.is_positive()); + } + + if(is_gt) + { + FUZZER_ASSERT_TRUE(!is_lt); + FUZZER_ASSERT_TRUE(d1.is_nonzero()); + FUZZER_ASSERT_TRUE(d2.is_nonzero()); + FUZZER_ASSERT_TRUE(d1.is_positive()); + FUZZER_ASSERT_TRUE(d2.is_negative()); + } + } + diff --git a/comm/third_party/botan/src/fuzzer/bn_sqr.cpp b/comm/third_party/botan/src/fuzzer/bn_sqr.cpp new file mode 100644 index 0000000000..f507c4a79c --- /dev/null +++ b/comm/third_party/botan/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/comm/third_party/botan/src/fuzzer/cert.cpp b/comm/third_party/botan/src/fuzzer/cert.cpp new file mode 100644 index 0000000000..215a294002 --- /dev/null +++ b/comm/third_party/botan/src/fuzzer/cert.cpp @@ -0,0 +1,22 @@ +/* +* (C) 2015,2016 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include "fuzzers.h" +#include <botan/x509cert.h> +#include <botan/data_src.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/comm/third_party/botan/src/fuzzer/crl.cpp b/comm/third_party/botan/src/fuzzer/crl.cpp new file mode 100644 index 0000000000..e41d523a91 --- /dev/null +++ b/comm/third_party/botan/src/fuzzer/crl.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/x509_crl.h> +#include <botan/data_src.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/comm/third_party/botan/src/fuzzer/divide.cpp b/comm/third_party/botan/src/fuzzer/divide.cpp new file mode 100644 index 0000000000..b6342ff7d8 --- /dev/null +++ b/comm/third_party/botan/src/fuzzer/divide.cpp @@ -0,0 +1,52 @@ +/* +* (C) 2015,2016,2018 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; + + // Save on allocations by making these static + static Botan::BigInt x, y, q, r, ct_q, ct_r, z; + + x = Botan::BigInt::decode(in, len / 2); + y = Botan::BigInt::decode(in + len / 2, len / 2); + + if(y == 0) + return; + + Botan::divide(x, y, q, r); + + FUZZER_ASSERT_TRUE(r < y); + + z = q*y + r; + + FUZZER_ASSERT_EQUAL(z, x); + + Botan::ct_divide(x, y, ct_q, ct_r); + + FUZZER_ASSERT_EQUAL(q, ct_q); + FUZZER_ASSERT_EQUAL(r, ct_r); + + // Now divide by just low byte of y + + y = y.byte_at(0); + if(y == 0) + y = 251; + Botan::divide(x, y, q, r); + + z = q*y + r; + FUZZER_ASSERT_EQUAL(z, x); + + uint8_t r8; + Botan::ct_divide_u8(x, y.byte_at(0), ct_q, r8); + FUZZER_ASSERT_EQUAL(ct_q, q); + FUZZER_ASSERT_EQUAL(r8, r.byte_at(0)); + + } + diff --git a/comm/third_party/botan/src/fuzzer/ecc_bp256.cpp b/comm/third_party/botan/src/fuzzer/ecc_bp256.cpp new file mode 100644 index 0000000000..4c1186f06a --- /dev/null +++ b/comm/third_party/botan/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/comm/third_party/botan/src/fuzzer/ecc_helper.h b/comm/third_party/botan/src/fuzzer/ecc_helper.h new file mode 100644 index 0000000000..4df23a5722 --- /dev/null +++ b/comm/third_party/botan/src/fuzzer/ecc_helper.h @@ -0,0 +1,107 @@ +/* +* (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/ec_group.h> +#include <botan/reducer.h> +#include <botan/numthry.h> + +namespace { + +inline std::ostream& operator<<(std::ostream& o, const Botan::PointGFp& point) + { + o << point.get_affine_x() << "," << point.get_affine_y(); + return o; + } + +Botan::BigInt decompress_point(bool yMod2, + const Botan::BigInt& x, + const Botan::BigInt& curve_p, + const Botan::BigInt& curve_a, + const Botan::BigInt& curve_b) + { + Botan::BigInt xpow3 = x * x * x; + + Botan::BigInt g = curve_a * x; + g += xpow3; + g += curve_b; + g = g % curve_p; + + Botan::BigInt z = ressol(g, curve_p); + + if(z < 0) + throw Botan::Exception("Could not perform square root"); + + if(z.get_bit(0) != yMod2) + z = curve_p - z; + + return z; + } + +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(); + + // This is shared across runs to reduce overhead + static std::vector<Botan::BigInt> ws(Botan::PointGFp::WORKSPACE_SIZE); + + 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 P1 = base_point * a; + const Botan::PointGFp Q1 = base_point * b; + const Botan::PointGFp R1 = base_point * c; + + const Botan::PointGFp S1 = P1 + Q1; + const Botan::PointGFp T1 = Q1 + P1; + + FUZZER_ASSERT_EQUAL(S1, R1); + FUZZER_ASSERT_EQUAL(T1, R1); + + const Botan::PointGFp P2 = group.blinded_base_point_multiply(a, fuzzer_rng(), ws); + const Botan::PointGFp Q2 = group.blinded_base_point_multiply(b, fuzzer_rng(), ws); + const Botan::PointGFp R2 = group.blinded_base_point_multiply(c, fuzzer_rng(), ws); + const Botan::PointGFp S2 = P2 + Q2; + const Botan::PointGFp T2 = Q2 + P2; + + FUZZER_ASSERT_EQUAL(S2, R2); + FUZZER_ASSERT_EQUAL(T2, R2); + + const Botan::PointGFp P3 = group.blinded_var_point_multiply(base_point, a, fuzzer_rng(), ws); + const Botan::PointGFp Q3 = group.blinded_var_point_multiply(base_point, b, fuzzer_rng(), ws); + const Botan::PointGFp R3 = group.blinded_var_point_multiply(base_point, c, fuzzer_rng(), ws); + const Botan::PointGFp S3 = P3 + Q3; + const Botan::PointGFp T3 = Q3 + P3; + + FUZZER_ASSERT_EQUAL(S3, R3); + FUZZER_ASSERT_EQUAL(T3, R3); + + FUZZER_ASSERT_EQUAL(S1, S2); + FUZZER_ASSERT_EQUAL(S1, S3); + + try + { + const auto yp = decompress_point(true, a, group.get_p(), group.get_a(), group.get_b()); + const auto pt_p = group.blinded_var_point_multiply(group.point(a, yp), b, fuzzer_rng(), ws); + + const auto yn = -yp; + const auto pt_n = group.blinded_var_point_multiply(group.point(a, yn), b, fuzzer_rng(), ws); + + FUZZER_ASSERT_EQUAL(pt_p, -pt_n); + } + catch(...) {} + } + +} + +#endif diff --git a/comm/third_party/botan/src/fuzzer/ecc_p256.cpp b/comm/third_party/botan/src/fuzzer/ecc_p256.cpp new file mode 100644 index 0000000000..c00be71b62 --- /dev/null +++ b/comm/third_party/botan/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/comm/third_party/botan/src/fuzzer/ecc_p384.cpp b/comm/third_party/botan/src/fuzzer/ecc_p384.cpp new file mode 100644 index 0000000000..1b58da9584 --- /dev/null +++ b/comm/third_party/botan/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/comm/third_party/botan/src/fuzzer/ecc_p521.cpp b/comm/third_party/botan/src/fuzzer/ecc_p521.cpp new file mode 100644 index 0000000000..3b9ed2d5c9 --- /dev/null +++ b/comm/third_party/botan/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/comm/third_party/botan/src/fuzzer/fuzzers.h b/comm/third_party/botan/src/fuzzer/fuzzers.h new file mode 100644 index 0000000000..ee78f7a6dd --- /dev/null +++ b/comm/third_party/botan/src/fuzzer/fuzzers.h @@ -0,0 +1,150 @@ +/* +* (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> + +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_WRITE_AND_CRASH(expr) \ + do { std::cerr << expr; abort(); } while(0) + +#define FUZZER_ASSERT_EQUAL(x, y) do { \ + if(x != y) { \ + FUZZER_WRITE_AND_CRASH(#x << " = " << x << " !=\n" \ + << #y << " = " << y << "\n"); \ + } } while(0) + +#define FUZZER_ASSERT_TRUE(e) \ + do { \ + if(!(e)) { \ + FUZZER_WRITE_AND_CRASH("Expression " << #e << " was false"); \ + } } while(0) + +#if defined(BOTAN_FUZZER_IS_AFL) || defined(BOTAN_FUZZER_IS_TEST) + +/* Stub for AFL */ + +#if defined(BOTAN_FUZZER_IS_AFL) && !defined(__AFL_COMPILER) + #error "Build configured for AFL but not being compiled by AFL compiler" +#endif + +#if defined(BOTAN_FUZZER_IS_TEST) + +#include <fstream> + +namespace { + +int fuzz_files(char* files[]) + { + for(size_t i = 0; files[i]; ++i) + { + std::ifstream in(files[i]); + + if(in.good()) + { + std::vector<uint8_t> buf(max_fuzzer_input_size); + in.read((char*)buf.data(), buf.size()); + const size_t got = in.gcount(); + buf.resize(got); + buf.shrink_to_fit(); + + LLVMFuzzerTestOneInput(buf.data(), got); + } + } + + return 0; + } + +} + +#endif + +int main(int argc, char* argv[]) + { + LLVMFuzzerInitialize(&argc, &argv); + +#if defined(BOTAN_FUZZER_IS_TEST) + if(argc > 1) + { + return fuzz_files(&argv[1]); + } +#endif + +#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); + } + } + +#elif defined(BOTAN_FUZZER_IS_KLEE) + +#include <klee/klee.h> + +int main(int argc, char* argv[]) + { + LLVMFuzzerInitialize(&argc, &argv); + + uint8_t input[max_fuzzer_input_size] = { 0 }; + klee_make_symbolic(&input, sizeof(input), "input"); + + size_t input_len = klee_range(0, sizeof(input), "input_len"); + + LLVMFuzzerTestOneInput(input, input_len); + } + +#endif + +#endif diff --git a/comm/third_party/botan/src/fuzzer/invert.cpp b/comm/third_party/botan/src/fuzzer/invert.cpp new file mode 100644 index 0000000000..5d34512f30 --- /dev/null +++ b/comm/third_party/botan/src/fuzzer/invert.cpp @@ -0,0 +1,82 @@ +/* +* (C) 2015,2016,2020 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ +#include "fuzzers.h" +#include <botan/numthry.h> + +namespace { + +Botan::BigInt ref_inverse_mod(const Botan::BigInt& n, const Botan::BigInt& mod) + { + if(n == 0 || mod < 2) + return 0; + if(n.is_even() && mod.is_even()) + return 0; + Botan::BigInt u = mod, v = n; + Botan::BigInt A = 1, B = 0, C = 0, D = 1; + + while(u.is_nonzero()) + { + const size_t u_zero_bits = Botan::low_zero_bits(u); + u >>= u_zero_bits; + for(size_t i = 0; i != u_zero_bits; ++i) + { + if(A.is_odd() || B.is_odd()) + { A += n; B -= mod; } + A >>= 1; B >>= 1; + } + + const size_t v_zero_bits = Botan::low_zero_bits(v); + v >>= v_zero_bits; + for(size_t i = 0; i != v_zero_bits; ++i) + { + if(C.is_odd() || D.is_odd()) + { C += n; D -= mod; } + C >>= 1; D >>= 1; + } + + if(u >= v) { u -= v; A -= C; B -= D; } + else { v -= u; C -= A; 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) + { + static const size_t max_bits = 4096; + + if(len > 2*max_bits/8) + return; + + const Botan::BigInt x = Botan::BigInt::decode(in, len / 2); + Botan::BigInt mod = Botan::BigInt::decode(in + len / 2, len - len / 2); + + if(mod < 2) + return; + + const Botan::BigInt lib = Botan::inverse_mod(x, mod); + const Botan::BigInt ref = ref_inverse_mod(x, mod); + + if(ref != lib) + { + FUZZER_WRITE_AND_CRASH("X = " << x << "\n" + << "Mod = " << mod << "\n" + << "GCD(X,Mod) = " << gcd(x, mod) << "\n" + << "RefInv(X,Mod) = " << ref << "\n" + << "LibInv(X,Mod) = " << lib << "\n" + << "RefCheck = " << (x*ref)%mod << "\n" + << "LibCheck = " << (x*lib)%mod << "\n"); + } + } + diff --git a/comm/third_party/botan/src/fuzzer/mem_pool.cpp b/comm/third_party/botan/src/fuzzer/mem_pool.cpp new file mode 100644 index 0000000000..7227462887 --- /dev/null +++ b/comm/third_party/botan/src/fuzzer/mem_pool.cpp @@ -0,0 +1,193 @@ +/* +* (C) 2018 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include "fuzzers.h" +#include <botan/internal/mem_pool.h> +#include <botan/internal/bit_ops.h> +#include <vector> +#include <map> +#include <utility> + +#include <stdlib.h> + +namespace { + +size_t compute_expected_alignment(size_t plen) + { + if(Botan::is_power_of_2(plen)) + { + return plen; + } + else + { + return 8; + } + } + +struct RawPage + { + public: + RawPage(void* p) : m_p(p) {} + ~RawPage() { std::free(m_p); } + + RawPage(const RawPage& other) = default; + RawPage& operator=(const RawPage& other) = default; + + RawPage(RawPage&& other) : m_p(nullptr) + { + std::swap(m_p, other.m_p); + } + + RawPage& operator=(RawPage&& other) + { + if(this != &other) + { + std::swap(m_p, other.m_p); + } + return (*this); + } + + void* ptr() const { return m_p; } + private: + void* m_p; + }; + +std::vector<RawPage> allocate_raw_pages(size_t count, size_t page_size) + { + std::vector<RawPage> pages; + pages.reserve(count); + + for(size_t i = 0; i != count; ++i) + { + void* ptr = nullptr; + + int rc = ::posix_memalign(&ptr, page_size, page_size); + FUZZER_ASSERT_EQUAL(rc, 0); + + if(ptr) + { + pages.push_back(RawPage(ptr)); + } + } + + return pages; + } + +} + +void fuzz(const uint8_t in[], size_t in_len) + { + const size_t page_count = 4; + const size_t page_size = 4096; + + // static to avoid repeated allocations + static std::vector<RawPage> raw_mem = allocate_raw_pages(page_count, page_size); + + std::vector<void*> mem_pages; + mem_pages.reserve(raw_mem.size()); + for(size_t i = 0; i != raw_mem.size(); ++i) + mem_pages.push_back(raw_mem[i].ptr()); + + Botan::Memory_Pool pool(mem_pages, page_size); + std::map<uint8_t*, size_t> ptrs; + + while(in_len > 0) + { + const uint8_t op = in[0] % 2; + size_t idx = (in[0] >> 1); + in += 1; + in_len -= 1; + + if(in_len > 0 && idx < 4) + { + idx = idx * 256 + in[0]; + in += 1; + in_len -= 1; + } + + //printf("%d %d\n", op, idx); + + if(op == 0) + { + const size_t plen = idx + 1; // ensure non-zero + uint8_t* p = static_cast<uint8_t*>(pool.allocate(plen)); + + if(p) + { + const size_t expected_alignment = compute_expected_alignment(plen); + const size_t alignment = reinterpret_cast<uintptr_t>(p) % expected_alignment; + if(alignment != 0) + { + FUZZER_WRITE_AND_CRASH("Pointer allocated non-aligned pointer " << static_cast<void*>(p) << " for len " << plen + << " expected " << expected_alignment << " got " << alignment); + } + + //printf("alloc %d -> %p\n", plen, p); + + for(size_t i = 0; i != plen; ++i) + { + if(p[i] != 0) + { + FUZZER_WRITE_AND_CRASH("Pool gave out non-zeroed memory"); + } + } + + // verify it becomes zeroed later + std::memset(p, idx, plen); + + auto insert = ptrs.insert(std::make_pair(p, plen)); + if(insert.second == false) + { + FUZZER_WRITE_AND_CRASH("Pointer " << static_cast<void*>(p) << " already existed\n"); + } + + auto itr = insert.first; + + // Verify this pointer doesn't overlap with the one before it + if(itr != ptrs.begin()) + { + auto before = std::prev(itr); + auto ptr_before = *before; + + if(ptr_before.first + ptr_before.second > p) + { + FUZZER_WRITE_AND_CRASH("Previous " << static_cast<void*>(ptr_before.first) << "/" << ptr_before.second << + " overlaps with new " << static_cast<void*>(p)); + } + } + + auto after = std::next(itr); + + if(after != ptrs.end()) + { + if(p + plen > after->first) + { + FUZZER_WRITE_AND_CRASH("New " << static_cast<void*>(p) << "/" << plen + << " overlaps following " << static_cast<void*>(after->first)); + } + } + } + } + else if(op == 1) + { + if(ptrs.empty()) + return; + + size_t which_ptr = idx % ptrs.size(); + + auto itr = ptrs.begin(); + + while(which_ptr-- > 0) + { + ++itr; + } + + //printf("free %p %d\n", itr->first, itr->second); + FUZZER_ASSERT_TRUE(pool.deallocate(itr->first, itr->second)); + ptrs.erase(itr); + } + } + } diff --git a/comm/third_party/botan/src/fuzzer/mode_padding.cpp b/comm/third_party/botan/src/fuzzer/mode_padding.cpp new file mode 100644 index 0000000000..c366530dd1 --- /dev/null +++ b/comm/third_party/botan/src/fuzzer/mode_padding.cpp @@ -0,0 +1,169 @@ +/* +* (C) 2018 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include "fuzzers.h" +#include <botan/mode_pad.h> +#include <botan/internal/tls_cbc.h> + +namespace { + +size_t ref_pkcs7_unpad(const uint8_t in[], size_t len) + { + if(len <= 2) + return len; + + const size_t padding_length = in[len-1]; + + if(padding_length == 0 || padding_length > len) + return len; + + const size_t padding_start = len - padding_length; + + for(size_t i = padding_start; i != len; ++i) + { + if(in[i] != padding_length) + return len; + } + + return len - padding_length; + } + +size_t ref_x923_unpad(const uint8_t in[], size_t len) + { + if(len <= 2) + return len; + + const size_t padding_length = in[len-1]; + + if(padding_length == 0 || padding_length > len) + return len; + const size_t padding_start = len - padding_length; + + for(size_t i = padding_start; i != len - 1; ++i) + { + if(in[i] != 0) + { + return len; + } + } + + return len - padding_length; + } + +size_t ref_oneandzero_unpad(const uint8_t in[], size_t len) + { + if(len <= 2) + return len; + + size_t idx = len - 1; + + for(;;) + { + if(in[idx] == 0) + { + if(idx == 0) + return len; + idx -= 1; + continue; + } + else if(in[idx] == 0x80) + { + return idx; + } + else + return len; + } + + return len; + } + +size_t ref_esp_unpad(const uint8_t in[], size_t len) + { + if(len <= 2) + return len; + + const size_t padding_bytes = in[len - 1]; + + if(padding_bytes == 0 || padding_bytes > len) + { + return len; + } + + const size_t padding_start = len - padding_bytes; + for(size_t i = padding_start; i != len; ++i) + { + if(in[i] != (i - padding_start + 1)) + { + return len; + } + } + + return len - padding_bytes; + } + +uint16_t ref_tls_cbc_unpad(const uint8_t in[], size_t len) + { + if(len == 0) + return 0; + + const size_t padding_length = in[(len-1)]; + + if(padding_length >= len) + return 0; + + /* + * TLS v1.0 and up require all the padding bytes be the same value + * and allows up to 255 bytes. + */ + for(size_t i = 0; i != 1 + padding_length; ++i) + { + if(in[(len-i-1)] != padding_length) + return 0; + } + return padding_length + 1; + } + +} + +void fuzz(const uint8_t in[], size_t len) + { + static Botan::PKCS7_Padding pkcs7; + static Botan::ANSI_X923_Padding x923; + static Botan::OneAndZeros_Padding oneandzero; + static Botan::ESP_Padding esp; + + if(pkcs7.valid_blocksize(len)) + { + const size_t ct_pkcs7 = pkcs7.unpad(in, len); + const size_t ref_pkcs7 = ref_pkcs7_unpad(in, len); + FUZZER_ASSERT_EQUAL(ct_pkcs7, ref_pkcs7); + } + + if(x923.valid_blocksize(len)) + { + const size_t ct_x923 = x923.unpad(in, len); + const size_t ref_x923 = ref_x923_unpad(in, len); + FUZZER_ASSERT_EQUAL(ct_x923, ref_x923); + } + + if(oneandzero.valid_blocksize(len)) + { + const size_t ct_oneandzero = oneandzero.unpad(in, len); + const size_t ref_oneandzero = ref_oneandzero_unpad(in, len); + FUZZER_ASSERT_EQUAL(ct_oneandzero, ref_oneandzero); + } + + if(esp.valid_blocksize(len)) + { + const size_t ct_esp = esp.unpad(in, len); + const size_t ref_esp = ref_esp_unpad(in, len); + FUZZER_ASSERT_EQUAL(ct_esp, ref_esp); + } + + const uint16_t ct_cbc = Botan::TLS::check_tls_cbc_padding(in, len); + const uint16_t ref_cbc = ref_tls_cbc_unpad(in, len); + FUZZER_ASSERT_EQUAL(ct_cbc, ref_cbc); + } diff --git a/comm/third_party/botan/src/fuzzer/oaep.cpp b/comm/third_party/botan/src/fuzzer/oaep.cpp new file mode 100644 index 0000000000..3d8275bded --- /dev/null +++ b/comm/third_party/botan/src/fuzzer/oaep.cpp @@ -0,0 +1,102 @@ +/* +* (C) 2018 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ +#include "fuzzers.h" + +#include <botan/oaep.h> +#include <botan/hex.h> + +namespace { + +Botan::secure_vector<uint8_t> +ref_oaep_unpad(uint8_t& valid_mask, + const uint8_t in[], size_t len, + const Botan::secure_vector<uint8_t>& Phash) + { + const size_t hlen = Phash.size(); + + if(len < 2*hlen + 1) + { + return Botan::secure_vector<uint8_t>(); + } + + for(size_t i = hlen; i != 2*hlen; ++i) + { + if(in[i] != Phash[i-hlen]) + { + return Botan::secure_vector<uint8_t>(); + } + } + + for(size_t i = 2*hlen; i != len; ++i) + { + if(in[i] != 0x00 && in[i] != 0x01) + { + return Botan::secure_vector<uint8_t>(); + } + + if(in[i] == 0x01) + { + valid_mask = 0xFF; + return Botan::secure_vector<uint8_t>(in + i + 1, in + len); + } + } + + return Botan::secure_vector<uint8_t>(); + } + +inline bool all_zeros(const Botan::secure_vector<uint8_t>& v) + { + for(size_t i = 0; i != v.size(); ++i) + { + if(v[i] != 0) + return false; + } + return true; + } + +} + +void fuzz(const uint8_t in[], size_t len) + { + static const Botan::secure_vector<uint8_t> Phash = { 1, 2, 3, 4 }; + + uint8_t lib_valid_mask = 0; + const Botan::secure_vector<uint8_t> lib_output = Botan::oaep_find_delim(lib_valid_mask, in, len, Phash); + FUZZER_ASSERT_TRUE(lib_valid_mask == 0 || lib_valid_mask == 0xFF); + + uint8_t ref_valid_mask = 0; + const Botan::secure_vector<uint8_t> ref_output = ref_oaep_unpad(ref_valid_mask, in, len, Phash); + FUZZER_ASSERT_TRUE(ref_valid_mask == 0 || ref_valid_mask == 0xFF); + + if(ref_valid_mask == 0xFF && lib_valid_mask == 0x00) + { + FUZZER_WRITE_AND_CRASH("Ref accepted but library rejected, output " << Botan::hex_encode(ref_output) << "\n"); + } + else if(ref_valid_mask == 0x00 && lib_valid_mask == 0xFF) + { + FUZZER_WRITE_AND_CRASH("Lib accepted but ref rejected, output = " << Botan::hex_encode(lib_output) << "\n"); + } + + if(ref_valid_mask == 0x00) + { + FUZZER_ASSERT_TRUE(all_zeros(ref_output)); + } + + if(lib_valid_mask == 0x00) + { + FUZZER_ASSERT_TRUE(all_zeros(lib_output)); + } + + if(ref_valid_mask && lib_valid_mask) + { + if(ref_output != lib_output) + { + FUZZER_WRITE_AND_CRASH("Ref and lib both accepted but produced different output:" + << " ref = " << Botan::hex_encode(ref_output) + << " lib = " << Botan::hex_encode(lib_output)); + } + } + } diff --git a/comm/third_party/botan/src/fuzzer/ocsp.cpp b/comm/third_party/botan/src/fuzzer/ocsp.cpp new file mode 100644 index 0000000000..0db265b8df --- /dev/null +++ b/comm/third_party/botan/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/comm/third_party/botan/src/fuzzer/os2ecp.cpp b/comm/third_party/botan/src/fuzzer/os2ecp.cpp new file mode 100644 index 0000000000..cb4a50b474 --- /dev/null +++ b/comm/third_party/botan/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 = group.OS2ECP(in, len); + } + 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/comm/third_party/botan/src/fuzzer/pkcs1.cpp b/comm/third_party/botan/src/fuzzer/pkcs1.cpp new file mode 100644 index 0000000000..8a297ff7f6 --- /dev/null +++ b/comm/third_party/botan/src/fuzzer/pkcs1.cpp @@ -0,0 +1,75 @@ +/* +* (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 + FUZZER_WRITE_AND_CRASH("Invalid valid_mask from unpad"); + } + 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 == true && ref_rejected == false) + { + FUZZER_WRITE_AND_CRASH("Library rejected input accepted by ref " + << Botan::hex_encode(ref_result)); + } + else if(ref_rejected == true && lib_rejected == false) + { + FUZZER_WRITE_AND_CRASH("Library accepted input rejected by ref " + << Botan::hex_encode(lib_result)); + } + // otherwise the two implementations agree + } diff --git a/comm/third_party/botan/src/fuzzer/pkcs8.cpp b/comm/third_party/botan/src/fuzzer/pkcs8.cpp new file mode 100644 index 0000000000..72a3046494 --- /dev/null +++ b/comm/third_party/botan/src/fuzzer/pkcs8.cpp @@ -0,0 +1,27 @@ +/* +* (C) 2015,2016 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include "fuzzers.h" +#include <botan/pk_keys.h> +#include <botan/pkcs8.h> +#include <botan/data_src.h> +#include <botan/ec_group.h> + +void fuzz(const uint8_t in[], size_t len) + { + try + { + Botan::DataSource_Memory input(in, len); + std::unique_ptr<Botan::Private_Key> key = Botan::PKCS8::load_key(input); + } + catch(Botan::Exception& e) { } + + /* + * This avoids OOMs in OSS-Fuzz caused by storing precomputations + * for thousands of curves randomly generated by the fuzzer. + */ + Botan::EC_Group::clear_registered_curve_data(); + } diff --git a/comm/third_party/botan/src/fuzzer/pow_mod.cpp b/comm/third_party/botan/src/fuzzer/pow_mod.cpp new file mode 100644 index 0000000000..28350480cb --- /dev/null +++ b/comm/third_party/botan/src/fuzzer/pow_mod.cpp @@ -0,0 +1,72 @@ +/* +* (C) 2016,2018 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include "fuzzers.h" +#include <botan/numthry.h> +#include <botan/reducer.h> + +namespace { + +Botan::BigInt simple_power_mod(Botan::BigInt x, + Botan::BigInt n, + const Botan::BigInt& p) + { + if(n == 0) + { + if(p == 1) + return 0; + return 1; + } + + Botan::Modular_Reducer mod_p(p); + 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 max_bits = 2048; + + if(len % 3 != 0) + return; + + const size_t part_size = len / 3; + + if(part_size * 8 > max_bits) + return; + + const Botan::BigInt g = Botan::BigInt::decode(in, part_size); + const Botan::BigInt x = Botan::BigInt::decode(in + part_size, part_size); + const Botan::BigInt p = Botan::BigInt::decode(in + 2*part_size, part_size); + + try + { + const Botan::BigInt ref = simple_power_mod(g, x, p); + const Botan::BigInt z = Botan::power_mod(g, x, p); + + if(ref != z) + { + FUZZER_WRITE_AND_CRASH("G = " << g << "\n" + << "X = " << x << "\n" + << "P = " << p << "\n" + << "Z = " << z << "\n" + << "R = " << ref << "\n"); + } + } + catch(Botan::Exception& e) {} + } diff --git a/comm/third_party/botan/src/fuzzer/redc_p192.cpp b/comm/third_party/botan/src/fuzzer/redc_p192.cpp new file mode 100644 index 0000000000..6898cdbb95 --- /dev/null +++ b/comm/third_party/botan/src/fuzzer/redc_p192.cpp @@ -0,0 +1,31 @@ +/* +* (C) 2015,2016 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include "fuzzers.h" +#include <botan/reducer.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 input = Botan::BigInt::decode(in, len); + + if(input < prime_2) + { + const Botan::BigInt ref = prime_redc.reduce(input); + + Botan::secure_vector<Botan::word> ws; + Botan::redc_p192(input, ws); + + FUZZER_ASSERT_EQUAL(ref, input); + } + } diff --git a/comm/third_party/botan/src/fuzzer/redc_p224.cpp b/comm/third_party/botan/src/fuzzer/redc_p224.cpp new file mode 100644 index 0000000000..b2dbac16e5 --- /dev/null +++ b/comm/third_party/botan/src/fuzzer/redc_p224.cpp @@ -0,0 +1,31 @@ +/* +* (C) 2015,2016 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include "fuzzers.h" +#include <botan/reducer.h> +#include <botan/curve_nistp.h> + +void fuzz(const uint8_t in[], size_t len) + { + if(len > 2*224/8) + return; + + 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 input = Botan::BigInt::decode(in, len); + + if(input < prime_2) + { + const Botan::BigInt ref = prime_redc.reduce(input); + + Botan::secure_vector<Botan::word> ws; + Botan::redc_p224(input, ws); + + FUZZER_ASSERT_EQUAL(ref, input); + } + } diff --git a/comm/third_party/botan/src/fuzzer/redc_p256.cpp b/comm/third_party/botan/src/fuzzer/redc_p256.cpp new file mode 100644 index 0000000000..4c3809f089 --- /dev/null +++ b/comm/third_party/botan/src/fuzzer/redc_p256.cpp @@ -0,0 +1,31 @@ +/* +* (C) 2015,2016 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include "fuzzers.h" +#include <botan/reducer.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 input = Botan::BigInt::decode(in, len); + + if(input < prime_2) + { + const Botan::BigInt ref = prime_redc.reduce(input); + + Botan::secure_vector<Botan::word> ws; + Botan::redc_p256(input, ws); + + FUZZER_ASSERT_EQUAL(ref, input); + } + } diff --git a/comm/third_party/botan/src/fuzzer/redc_p384.cpp b/comm/third_party/botan/src/fuzzer/redc_p384.cpp new file mode 100644 index 0000000000..1c3a777a0a --- /dev/null +++ b/comm/third_party/botan/src/fuzzer/redc_p384.cpp @@ -0,0 +1,31 @@ +/* +* (C) 2015,2016 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include "fuzzers.h" +#include <botan/reducer.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 input = Botan::BigInt::decode(in, len); + + if(input < prime_2) + { + const Botan::BigInt ref = prime_redc.reduce(input); + + Botan::secure_vector<Botan::word> ws; + Botan::redc_p384(input, ws); + + FUZZER_ASSERT_EQUAL(ref, input); + } + } diff --git a/comm/third_party/botan/src/fuzzer/redc_p521.cpp b/comm/third_party/botan/src/fuzzer/redc_p521.cpp new file mode 100644 index 0000000000..e148c94bb7 --- /dev/null +++ b/comm/third_party/botan/src/fuzzer/redc_p521.cpp @@ -0,0 +1,31 @@ +/* +* (C) 2015,2016 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include "fuzzers.h" +#include <botan/reducer.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 input = Botan::BigInt::decode(in, len); + + if(input < prime_2) + { + const Botan::BigInt ref = prime_redc.reduce(input); + + Botan::secure_vector<Botan::word> ws; + Botan::redc_p521(input, ws); + + FUZZER_ASSERT_EQUAL(ref, input); + } + } diff --git a/comm/third_party/botan/src/fuzzer/ressol.cpp b/comm/third_party/botan/src/fuzzer/ressol.cpp new file mode 100644 index 0000000000..99d48f98be --- /dev/null +++ b/comm/third_party/botan/src/fuzzer/ressol.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/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) + { + FUZZER_WRITE_AND_CRASH("A = " << a << "\n" + << "P = " << p << "\n" + << "R = " << a_sqrt << "\n" + << "Z = " << z << "\n"); + } + } + } + catch(Botan::Exception& e) {} + + return; + } + diff --git a/comm/third_party/botan/src/fuzzer/tls_client.cpp b/comm/third_party/botan/src/fuzzer/tls_client.cpp new file mode 100644 index 0000000000..a5c8137bfc --- /dev/null +++ b/comm/third_party/botan/src/fuzzer/tls_client.cpp @@ -0,0 +1,130 @@ +/* +* (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"); + } + }; + +class Fuzzer_TLS_Policy : public Botan::TLS::Policy + { + public: + std::vector<uint16_t> ciphersuite_list(Botan::TLS::Protocol_Version version, + bool have_srp) const + { + std::vector<uint16_t> ciphersuites; + + for(auto&& suite : Botan::TLS::Ciphersuite::all_known_ciphersuites()) + { + if(suite.valid() == false) + continue; + + // Are we doing SRP? + if(!have_srp && suite.kex_method() == Botan::TLS::Kex_Algo::SRP_SHA) + continue; + + if(!version.supports_aead_modes()) + { + // Are we doing AEAD in a non-AEAD version? + if(suite.mac_algo() == "AEAD") + continue; + + // Older (v1.0/v1.1) versions also do not support any hash but SHA-1 + if(suite.mac_algo() != "SHA-1") + continue; + } + + ciphersuites.push_back(suite.ciphersuite_code()); + } + + return ciphersuites; + } + }; + +class Fuzzer_TLS_Client_Callbacks : public Botan::TLS::Callbacks + { + public: + void tls_emit_data(const uint8_t[], size_t) override + { + // discard + } + + void tls_record_received(uint64_t, const uint8_t[], size_t) override + { + // ignore peer data + } + + void tls_alert(Botan::TLS::Alert) override + { + // ignore alert + } + + bool tls_session_established(const Botan::TLS::Session&) override + { + return true; // cache it + } + + void tls_verify_cert_chain( + const std::vector<Botan::X509_Certificate>& cert_chain, + const std::vector<std::shared_ptr<const Botan::OCSP::Response>>& ocsp_responses, + const std::vector<Botan::Certificate_Store*>& trusted_roots, + Botan::Usage_Type usage, + const std::string& hostname, + const Botan::TLS::Policy& policy) override + { + try + { + // try to validate to exercise those code paths + Botan::TLS::Callbacks::tls_verify_cert_chain(cert_chain, ocsp_responses, + trusted_roots, usage, hostname, policy); + } + catch(...) + { + // ignore validation result + } + } + + }; + +void fuzz(const uint8_t in[], size_t len) + { + if(len == 0) + return; + + Botan::TLS::Session_Manager_Noop session_manager; + Fuzzer_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_Callbacks callbacks; + Fuzzer_TLS_Client_Creds creds; + + Botan::TLS::Client client(callbacks, + session_manager, + creds, + policy, + fuzzer_rng(), + info, + client_offer); + + try + { + client.received_data(in, len); + } + catch(std::exception& e) + { + } + + } + diff --git a/comm/third_party/botan/src/fuzzer/tls_client_hello.cpp b/comm/third_party/botan/src/fuzzer/tls_client_hello.cpp new file mode 100644 index 0000000000..28c77c9b6d --- /dev/null +++ b/comm/third_party/botan/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/comm/third_party/botan/src/fuzzer/tls_server.cpp b/comm/third_party/botan/src/fuzzer/tls_server.cpp new file mode 100644 index 0000000000..d45ff5f5ce --- /dev/null +++ b/comm/third_party/botan/src/fuzzer/tls_server.cpp @@ -0,0 +1,227 @@ +/* +* (C) 2015,2016 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include "fuzzers.h" +#include <botan/tls_server.h> +#include <botan/data_src.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; + }; + +class Fuzzer_TLS_Policy : public Botan::TLS::Policy + { + public: + std::vector<uint16_t> ciphersuite_list(Botan::TLS::Protocol_Version version, + bool have_srp) const + { + std::vector<uint16_t> ciphersuites; + + for(auto&& suite : Botan::TLS::Ciphersuite::all_known_ciphersuites()) + { + if(suite.valid() == false) + continue; + + // Are we doing SRP? + if(!have_srp && suite.kex_method() == Botan::TLS::Kex_Algo::SRP_SHA) + continue; + + if(!version.supports_aead_modes()) + { + // Are we doing AEAD in a non-AEAD version? + if(suite.mac_algo() == "AEAD") + continue; + + // Older (v1.0/v1.1) versions also do not support any hash but SHA-1 + if(suite.mac_algo() != "SHA-1") + continue; + } + + ciphersuites.push_back(suite.ciphersuite_code()); + } + + return ciphersuites; + } + }; + +class Fuzzer_TLS_Server_Callbacks : public Botan::TLS::Callbacks + { + public: + void tls_emit_data(const uint8_t[], size_t) override + { + // discard + } + + void tls_record_received(uint64_t, const uint8_t[], size_t) override + { + // ignore peer data + } + + void tls_alert(Botan::TLS::Alert) override + { + // ignore alert + } + + bool tls_session_established(const Botan::TLS::Session&) override + { + return true; // cache it + } + + std::string tls_server_choose_app_protocol(const std::vector<std::string>& client_protos) override + { + if(client_protos.size() > 1) + return client_protos[0]; + else + return "fuzzy"; + } + + void tls_verify_cert_chain( + const std::vector<Botan::X509_Certificate>& cert_chain, + const std::vector<std::shared_ptr<const Botan::OCSP::Response>>& ocsp_responses, + const std::vector<Botan::Certificate_Store*>& trusted_roots, + Botan::Usage_Type usage, + const std::string& hostname, + const Botan::TLS::Policy& policy) override + { + try + { + // try to validate to exercise those code paths + Botan::TLS::Callbacks::tls_verify_cert_chain(cert_chain, ocsp_responses, + trusted_roots, usage, hostname, policy); + } + catch(...) + { + // ignore validation result + } + } + + }; + +void fuzz(const uint8_t in[], size_t len) + { + if(len <= 1) + return; + + Botan::TLS::Session_Manager_Noop session_manager; + Fuzzer_TLS_Policy policy; + Botan::TLS::Server_Information info("server.name", 443); + Fuzzer_TLS_Server_Creds creds; + Fuzzer_TLS_Server_Callbacks callbacks; + + const bool is_datagram = in[0] & 1; + + Botan::TLS::Server server(callbacks, + session_manager, + creds, + policy, + fuzzer_rng(), + is_datagram); + + try + { + server.received_data(in + 1, len - 1); + } + catch(std::exception& e) + { + } + } diff --git a/comm/third_party/botan/src/fuzzer/uri.cpp b/comm/third_party/botan/src/fuzzer/uri.cpp new file mode 100644 index 0000000000..89066d283e --- /dev/null +++ b/comm/third_party/botan/src/fuzzer/uri.cpp @@ -0,0 +1,20 @@ +/* +* (C) 2019 Nuno Goncalves <nunojpg@gmail.com> +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include "fuzzers.h" +#include <botan/internal/uri.h> + +void fuzz(const uint8_t in[], size_t len) + { + if(len > max_fuzzer_input_size) + return; + + try + { + Botan::URI::fromAny(std::string(reinterpret_cast<const char*>(in), len)); + } + catch(Botan::Exception& e) { } + } diff --git a/comm/third_party/botan/src/fuzzer/x509_dn.cpp b/comm/third_party/botan/src/fuzzer/x509_dn.cpp new file mode 100644 index 0000000000..9fc062cfb4 --- /dev/null +++ b/comm/third_party/botan/src/fuzzer/x509_dn.cpp @@ -0,0 +1,41 @@ +/* +* (C) 2019 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include "fuzzers.h" +#include <botan/pkix_types.h> +#include <botan/ber_dec.h> +#include <botan/hex.h> + +void fuzz(const uint8_t in[], size_t len) + { + Botan::X509_DN dn1; + Botan::X509_DN dn2; + + try + { + Botan::BER_Decoder ber(in, len); + dn1.decode_from(ber); + dn2.decode_from(ber); + } + catch(...) { return; } + + const bool eq = dn1 == dn2; + const bool lt1 = dn1 < dn2; + const bool lt2 = dn2 < dn1; + + if(lt1 == false && lt2 == false) + { + FUZZER_ASSERT_TRUE(eq); + } + else + { + // one is less than the other + FUZZER_ASSERT_TRUE(lt1 || lt2); + + // it is not the case that both are less than the other + FUZZER_ASSERT_TRUE(!lt1 || !lt2); + } + } |