summaryrefslogtreecommitdiffstats
path: root/comm/third_party/botan/src/fuzzer
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /comm/third_party/botan/src/fuzzer
parentInitial commit. (diff)
downloadthunderbird-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')
-rw-r--r--comm/third_party/botan/src/fuzzer/asn1.cpp43
-rw-r--r--comm/third_party/botan/src/fuzzer/barrett.cpp49
-rw-r--r--comm/third_party/botan/src/fuzzer/bn_cmp.cpp74
-rw-r--r--comm/third_party/botan/src/fuzzer/bn_sqr.cpp24
-rw-r--r--comm/third_party/botan/src/fuzzer/cert.cpp22
-rw-r--r--comm/third_party/botan/src/fuzzer/crl.cpp19
-rw-r--r--comm/third_party/botan/src/fuzzer/divide.cpp52
-rw-r--r--comm/third_party/botan/src/fuzzer/ecc_bp256.cpp16
-rw-r--r--comm/third_party/botan/src/fuzzer/ecc_helper.h107
-rw-r--r--comm/third_party/botan/src/fuzzer/ecc_p256.cpp15
-rw-r--r--comm/third_party/botan/src/fuzzer/ecc_p384.cpp15
-rw-r--r--comm/third_party/botan/src/fuzzer/ecc_p521.cpp15
-rw-r--r--comm/third_party/botan/src/fuzzer/fuzzers.h150
-rw-r--r--comm/third_party/botan/src/fuzzer/invert.cpp82
-rw-r--r--comm/third_party/botan/src/fuzzer/mem_pool.cpp193
-rw-r--r--comm/third_party/botan/src/fuzzer/mode_padding.cpp169
-rw-r--r--comm/third_party/botan/src/fuzzer/oaep.cpp102
-rw-r--r--comm/third_party/botan/src/fuzzer/ocsp.cpp17
-rw-r--r--comm/third_party/botan/src/fuzzer/os2ecp.cpp44
-rw-r--r--comm/third_party/botan/src/fuzzer/pkcs1.cpp75
-rw-r--r--comm/third_party/botan/src/fuzzer/pkcs8.cpp27
-rw-r--r--comm/third_party/botan/src/fuzzer/pow_mod.cpp72
-rw-r--r--comm/third_party/botan/src/fuzzer/redc_p192.cpp31
-rw-r--r--comm/third_party/botan/src/fuzzer/redc_p224.cpp31
-rw-r--r--comm/third_party/botan/src/fuzzer/redc_p256.cpp31
-rw-r--r--comm/third_party/botan/src/fuzzer/redc_p384.cpp31
-rw-r--r--comm/third_party/botan/src/fuzzer/redc_p521.cpp31
-rw-r--r--comm/third_party/botan/src/fuzzer/ressol.cpp44
-rw-r--r--comm/third_party/botan/src/fuzzer/tls_client.cpp130
-rw-r--r--comm/third_party/botan/src/fuzzer/tls_client_hello.cpp18
-rw-r--r--comm/third_party/botan/src/fuzzer/tls_server.cpp227
-rw-r--r--comm/third_party/botan/src/fuzzer/uri.cpp20
-rw-r--r--comm/third_party/botan/src/fuzzer/x509_dn.cpp41
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);
+ }
+ }