summaryrefslogtreecommitdiffstats
path: root/comm/third_party/botan/src/lib/entropy
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--comm/third_party/botan/src/lib/entropy/dev_random/dev_random.cpp122
-rw-r--r--comm/third_party/botan/src/lib/entropy/dev_random/dev_random.h37
-rw-r--r--comm/third_party/botan/src/lib/entropy/dev_random/info.txt11
-rw-r--r--comm/third_party/botan/src/lib/entropy/entropy_src.h87
-rw-r--r--comm/third_party/botan/src/lib/entropy/entropy_srcs.cpp235
-rw-r--r--comm/third_party/botan/src/lib/entropy/getentropy/getentropy.cpp35
-rw-r--r--comm/third_party/botan/src/lib/entropy/getentropy/getentropy.h28
-rw-r--r--comm/third_party/botan/src/lib/entropy/getentropy/info.txt11
-rw-r--r--comm/third_party/botan/src/lib/entropy/info.txt7
-rw-r--r--comm/third_party/botan/src/lib/entropy/proc_walk/info.txt11
-rw-r--r--comm/third_party/botan/src/lib/entropy/proc_walk/proc_walk.cpp154
-rw-r--r--comm/third_party/botan/src/lib/entropy/proc_walk/proc_walk.h45
-rw-r--r--comm/third_party/botan/src/lib/entropy/rdseed/info.txt19
-rw-r--r--comm/third_party/botan/src/lib/entropy/rdseed/rdseed.cpp97
-rw-r--r--comm/third_party/botan/src/lib/entropy/rdseed/rdseed.h28
-rw-r--r--comm/third_party/botan/src/lib/entropy/win32_stats/es_win32.cpp59
-rw-r--r--comm/third_party/botan/src/lib/entropy/win32_stats/es_win32.h27
-rw-r--r--comm/third_party/botan/src/lib/entropy/win32_stats/info.txt15
18 files changed, 1028 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/lib/entropy/dev_random/dev_random.cpp b/comm/third_party/botan/src/lib/entropy/dev_random/dev_random.cpp
new file mode 100644
index 0000000000..44fcbace3f
--- /dev/null
+++ b/comm/third_party/botan/src/lib/entropy/dev_random/dev_random.cpp
@@ -0,0 +1,122 @@
+/*
+* Reader of /dev/random and company
+* (C) 1999-2009,2013 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/internal/dev_random.h>
+#include <botan/exceptn.h>
+
+#include <sys/types.h>
+#include <sys/select.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+namespace Botan {
+
+/**
+Device_EntropySource constructor
+Open a file descriptor to each (available) device in fsnames
+*/
+Device_EntropySource::Device_EntropySource(const std::vector<std::string>& fsnames)
+ {
+#ifndef O_NONBLOCK
+ #define O_NONBLOCK 0
+#endif
+
+#ifndef O_NOCTTY
+ #define O_NOCTTY 0
+#endif
+
+ const int flags = O_RDONLY | O_NONBLOCK | O_NOCTTY;
+
+ m_max_fd = 0;
+
+ for(auto fsname : fsnames)
+ {
+ int fd = ::open(fsname.c_str(), flags);
+
+ if(fd < 0)
+ {
+ /*
+ ENOENT or EACCES is normal as some of the named devices may not exist
+ on this system. But any other errno value probably indicates
+ either a bug in the application or file descriptor exhaustion.
+ */
+ if(errno != ENOENT && errno != EACCES)
+ throw System_Error("Opening OS RNG device failed", errno);
+ }
+ else
+ {
+ if(fd > FD_SETSIZE)
+ {
+ ::close(fd);
+ throw Invalid_State("Open of OS RNG succeeded but returned fd is too large for fd_set");
+ }
+
+ m_dev_fds.push_back(fd);
+ m_max_fd = std::max(m_max_fd, fd);
+ }
+ }
+ }
+
+/**
+Device_EntropySource destructor: close all open devices
+*/
+Device_EntropySource::~Device_EntropySource()
+ {
+ for(int fd : m_dev_fds)
+ {
+ // ignoring return value here, can't throw in destructor anyway
+ ::close(fd);
+ }
+ }
+
+/**
+* Gather entropy from a RNG device
+*/
+size_t Device_EntropySource::poll(RandomNumberGenerator& rng)
+ {
+ size_t bits = 0;
+
+ if(m_dev_fds.size() > 0)
+ {
+ fd_set read_set;
+ FD_ZERO(&read_set);
+
+ for(int dev_fd : m_dev_fds)
+ {
+ FD_SET(dev_fd, &read_set);
+ }
+
+ secure_vector<uint8_t> io_buf(BOTAN_SYSTEM_RNG_POLL_REQUEST);
+
+ struct ::timeval timeout;
+ timeout.tv_sec = (BOTAN_SYSTEM_RNG_POLL_TIMEOUT_MS / 1000);
+ timeout.tv_usec = (BOTAN_SYSTEM_RNG_POLL_TIMEOUT_MS % 1000) * 1000;
+
+ if(::select(m_max_fd + 1, &read_set, nullptr, nullptr, &timeout) > 0)
+ {
+ for(int dev_fd : m_dev_fds)
+ {
+ if(FD_ISSET(dev_fd, &read_set))
+ {
+ const ssize_t got = ::read(dev_fd, io_buf.data(), io_buf.size());
+
+ if(got > 0)
+ {
+ rng.add_entropy(io_buf.data(), static_cast<size_t>(got));
+ bits += got * 8;
+ }
+ }
+ }
+ }
+ }
+
+ return bits;
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/entropy/dev_random/dev_random.h b/comm/third_party/botan/src/lib/entropy/dev_random/dev_random.h
new file mode 100644
index 0000000000..6195f85648
--- /dev/null
+++ b/comm/third_party/botan/src/lib/entropy/dev_random/dev_random.h
@@ -0,0 +1,37 @@
+/*
+* /dev/random EntropySource
+* (C) 1999-2009 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_ENTROPY_SRC_DEVICE_H_
+#define BOTAN_ENTROPY_SRC_DEVICE_H_
+
+#include <botan/entropy_src.h>
+#include <vector>
+#include <string>
+
+namespace Botan {
+
+/**
+* Entropy source reading from kernel devices like /dev/random
+*/
+class Device_EntropySource final : public Entropy_Source
+ {
+ public:
+ std::string name() const override { return "dev_random"; }
+
+ size_t poll(RandomNumberGenerator& rng) override;
+
+ explicit Device_EntropySource(const std::vector<std::string>& fsnames);
+
+ ~Device_EntropySource();
+ private:
+ std::vector<int> m_dev_fds;
+ int m_max_fd;
+ };
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/entropy/dev_random/info.txt b/comm/third_party/botan/src/lib/entropy/dev_random/info.txt
new file mode 100644
index 0000000000..3872411f30
--- /dev/null
+++ b/comm/third_party/botan/src/lib/entropy/dev_random/info.txt
@@ -0,0 +1,11 @@
+<defines>
+ENTROPY_SRC_DEV_RANDOM -> 20131128
+</defines>
+
+<header:internal>
+dev_random.h
+</header:internal>
+
+<os_features>
+dev_random,posix1
+</os_features>
diff --git a/comm/third_party/botan/src/lib/entropy/entropy_src.h b/comm/third_party/botan/src/lib/entropy/entropy_src.h
new file mode 100644
index 0000000000..56e5bd53e5
--- /dev/null
+++ b/comm/third_party/botan/src/lib/entropy/entropy_src.h
@@ -0,0 +1,87 @@
+/*
+* EntropySource
+* (C) 2008,2009,2014,2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_ENTROPY_H_
+#define BOTAN_ENTROPY_H_
+
+#include <botan/secmem.h>
+#include <botan/rng.h>
+#include <string>
+#include <chrono>
+#include <memory>
+#include <vector>
+
+namespace Botan {
+
+class RandomNumberGenerator;
+
+/**
+* Abstract interface to a source of entropy
+*/
+class BOTAN_PUBLIC_API(2,0) Entropy_Source
+ {
+ public:
+ /**
+ * Return a new entropy source of a particular type, or null
+ * Each entropy source may require substantial resources (eg, a file handle
+ * or socket instance), so try to share them among multiple RNGs, or just
+ * use the preconfigured global list accessed by Entropy_Sources::global_sources()
+ */
+ static std::unique_ptr<Entropy_Source> create(const std::string& type);
+
+ /**
+ * @return name identifying this entropy source
+ */
+ virtual std::string name() const = 0;
+
+ /**
+ * Perform an entropy gathering poll
+ * @param rng will be provided with entropy via calls to add_entropy
+ * @return conservative estimate of actual entropy added to rng during poll
+ */
+ virtual size_t poll(RandomNumberGenerator& rng) = 0;
+
+ Entropy_Source() = default;
+ Entropy_Source(const Entropy_Source& other) = delete;
+ Entropy_Source(Entropy_Source&& other) = delete;
+ Entropy_Source& operator=(const Entropy_Source& other) = delete;
+
+ virtual ~Entropy_Source() = default;
+ };
+
+class BOTAN_PUBLIC_API(2,0) Entropy_Sources final
+ {
+ public:
+ static Entropy_Sources& global_sources();
+
+ void add_source(std::unique_ptr<Entropy_Source> src);
+
+ std::vector<std::string> enabled_sources() const;
+
+ size_t poll(RandomNumberGenerator& rng,
+ size_t bits,
+ std::chrono::milliseconds timeout);
+
+ /**
+ * Poll just a single named source. Ordinally only used for testing
+ */
+ size_t poll_just(RandomNumberGenerator& rng, const std::string& src);
+
+ Entropy_Sources() = default;
+ explicit Entropy_Sources(const std::vector<std::string>& sources);
+
+ Entropy_Sources(const Entropy_Sources& other) = delete;
+ Entropy_Sources(Entropy_Sources&& other) = delete;
+ Entropy_Sources& operator=(const Entropy_Sources& other) = delete;
+
+ private:
+ std::vector<std::unique_ptr<Entropy_Source>> m_srcs;
+ };
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/entropy/entropy_srcs.cpp b/comm/third_party/botan/src/lib/entropy/entropy_srcs.cpp
new file mode 100644
index 0000000000..e6573e2963
--- /dev/null
+++ b/comm/third_party/botan/src/lib/entropy/entropy_srcs.cpp
@@ -0,0 +1,235 @@
+/*
+* Entropy Source Polling
+* (C) 2008-2010,2015 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/entropy_src.h>
+#include <botan/rng.h>
+
+#if defined(BOTAN_HAS_SYSTEM_RNG)
+ #include <botan/system_rng.h>
+#endif
+
+#if defined(BOTAN_HAS_PROCESSOR_RNG)
+ #include <botan/processor_rng.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_RDRAND)
+ #include <botan/internal/rdrand.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_RDSEED)
+ #include <botan/internal/rdseed.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_DARN)
+ #include <botan/internal/p9_darn.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_DEV_RANDOM)
+ #include <botan/internal/dev_random.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_WIN32)
+ #include <botan/internal/es_win32.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_PROC_WALKER)
+ #include <botan/internal/proc_walk.h>
+ #include <botan/internal/os_utils.h>
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_GETENTROPY)
+ #include <botan/internal/getentropy.h>
+#endif
+
+namespace Botan {
+
+namespace {
+
+#if defined(BOTAN_HAS_SYSTEM_RNG)
+
+class System_RNG_EntropySource final : public Entropy_Source
+ {
+ public:
+ size_t poll(RandomNumberGenerator& rng) override
+ {
+ const size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS;
+ rng.reseed_from_rng(system_rng(), poll_bits);
+ return poll_bits;
+ }
+
+ std::string name() const override { return "system_rng"; }
+ };
+
+#endif
+
+#if defined(BOTAN_HAS_PROCESSOR_RNG)
+
+class Processor_RNG_EntropySource final : public Entropy_Source
+ {
+ public:
+ size_t poll(RandomNumberGenerator& rng) override
+ {
+ /*
+ * Intel's documentation for RDRAND at
+ * https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide
+ * claims that software can guarantee a reseed event by polling enough data:
+ * "There is an upper bound of 511 samples per seed in the implementation
+ * where samples are 128 bits in size and can provide two 64-bit random
+ * numbers each."
+ *
+ * By requesting 65536 bits we are asking for 512 samples and thus are assured
+ * that at some point in producing the output, at least one reseed of the
+ * internal state will occur.
+ *
+ * The reseeding conditions of the POWER and ARM processor RNGs are not known
+ * but probably work in a somewhat similar manner. The exact amount requested
+ * may be tweaked if and when such conditions become publically known.
+ */
+ const size_t poll_bits = 65536;
+ rng.reseed_from_rng(m_hwrng, poll_bits);
+ // Avoid trusting a black box, don't count this as contributing entropy:
+ return 0;
+ }
+
+ std::string name() const override { return m_hwrng.name(); }
+ private:
+ Processor_RNG m_hwrng;
+ };
+
+#endif
+
+}
+
+std::unique_ptr<Entropy_Source> Entropy_Source::create(const std::string& name)
+ {
+#if defined(BOTAN_HAS_SYSTEM_RNG)
+ if(name == "system_rng" || name == "win32_cryptoapi")
+ {
+ return std::unique_ptr<Entropy_Source>(new System_RNG_EntropySource);
+ }
+#endif
+
+#if defined(BOTAN_HAS_PROCESSOR_RNG)
+ if(name == "hwrng" || name == "rdrand" || name == "p9_darn")
+ {
+ if(Processor_RNG::available())
+ {
+ return std::unique_ptr<Entropy_Source>(new Processor_RNG_EntropySource);
+ }
+ }
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_RDSEED)
+ if(name == "rdseed")
+ {
+ return std::unique_ptr<Entropy_Source>(new Intel_Rdseed);
+ }
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_GETENTROPY)
+ if(name == "getentropy")
+ {
+ return std::unique_ptr<Entropy_Source>(new Getentropy);
+ }
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_DEV_RANDOM)
+ if(name == "dev_random")
+ {
+ return std::unique_ptr<Entropy_Source>(new Device_EntropySource(BOTAN_SYSTEM_RNG_POLL_DEVICES));
+ }
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_PROC_WALKER)
+ if(name == "proc_walk" && OS::running_in_privileged_state() == false)
+ {
+ const std::string root_dir = BOTAN_ENTROPY_PROC_FS_PATH;
+ if(!root_dir.empty())
+ return std::unique_ptr<Entropy_Source>(new ProcWalking_EntropySource(root_dir));
+ }
+#endif
+
+#if defined(BOTAN_HAS_ENTROPY_SRC_WIN32)
+ if(name == "system_stats")
+ {
+ return std::unique_ptr<Entropy_Source>(new Win32_EntropySource);
+ }
+#endif
+
+ BOTAN_UNUSED(name);
+ return std::unique_ptr<Entropy_Source>();
+ }
+
+void Entropy_Sources::add_source(std::unique_ptr<Entropy_Source> src)
+ {
+ if(src.get())
+ {
+ m_srcs.push_back(std::move(src));
+ }
+ }
+
+std::vector<std::string> Entropy_Sources::enabled_sources() const
+ {
+ std::vector<std::string> sources;
+ for(size_t i = 0; i != m_srcs.size(); ++i)
+ {
+ sources.push_back(m_srcs[i]->name());
+ }
+ return sources;
+ }
+
+size_t Entropy_Sources::poll(RandomNumberGenerator& rng,
+ size_t poll_bits,
+ std::chrono::milliseconds timeout)
+ {
+ typedef std::chrono::system_clock clock;
+
+ auto deadline = clock::now() + timeout;
+
+ size_t bits_collected = 0;
+
+ for(size_t i = 0; i != m_srcs.size(); ++i)
+ {
+ bits_collected += m_srcs[i]->poll(rng);
+
+ if (bits_collected >= poll_bits || clock::now() > deadline)
+ break;
+ }
+
+ return bits_collected;
+ }
+
+size_t Entropy_Sources::poll_just(RandomNumberGenerator& rng, const std::string& the_src)
+ {
+ for(size_t i = 0; i != m_srcs.size(); ++i)
+ {
+ if(m_srcs[i]->name() == the_src)
+ {
+ return m_srcs[i]->poll(rng);
+ }
+ }
+
+ return 0;
+ }
+
+Entropy_Sources::Entropy_Sources(const std::vector<std::string>& sources)
+ {
+ for(auto&& src_name : sources)
+ {
+ add_source(Entropy_Source::create(src_name));
+ }
+ }
+
+Entropy_Sources& Entropy_Sources::global_sources()
+ {
+ static Entropy_Sources global_entropy_sources(BOTAN_ENTROPY_DEFAULT_SOURCES);
+
+ return global_entropy_sources;
+ }
+
+}
+
diff --git a/comm/third_party/botan/src/lib/entropy/getentropy/getentropy.cpp b/comm/third_party/botan/src/lib/entropy/getentropy/getentropy.cpp
new file mode 100644
index 0000000000..7e87367a20
--- /dev/null
+++ b/comm/third_party/botan/src/lib/entropy/getentropy/getentropy.cpp
@@ -0,0 +1,35 @@
+/*
+* System Call getentropy(2)
+* (C) 2017 Alexander Bluhm (genua GmbH)
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/internal/getentropy.h>
+
+#if defined(BOTAN_TARGET_OS_IS_OPENBSD) || defined(BOTAN_TARGET_OS_IS_FREEBSD)
+ #include <unistd.h>
+#else
+ #include <sys/random.h>
+#endif
+
+namespace Botan {
+
+/**
+* Gather 256 bytes entropy from getentropy(2). Note that maximum
+* buffer size is limited to 256 bytes. On OpenBSD this does neither
+* block nor fail.
+*/
+size_t Getentropy::poll(RandomNumberGenerator& rng)
+ {
+ secure_vector<uint8_t> buf(256);
+
+ if(::getentropy(buf.data(), buf.size()) == 0)
+ {
+ rng.add_entropy(buf.data(), buf.size());
+ return buf.size() * 8;
+ }
+
+ return 0;
+ }
+}
diff --git a/comm/third_party/botan/src/lib/entropy/getentropy/getentropy.h b/comm/third_party/botan/src/lib/entropy/getentropy/getentropy.h
new file mode 100644
index 0000000000..26783cf78a
--- /dev/null
+++ b/comm/third_party/botan/src/lib/entropy/getentropy/getentropy.h
@@ -0,0 +1,28 @@
+/*
+* Entropy Source Using OpenBSD getentropy(2) system call
+* (C) 2017 Alexander Bluhm (genua GmbH)
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_ENTROPY_SRC_GETENTROPY_H_
+#define BOTAN_ENTROPY_SRC_GETENTROPY_H_
+
+#include <botan/entropy_src.h>
+
+namespace Botan {
+
+/**
+* Entropy source using the getentropy(2) system call first introduced in
+* OpenBSD 5.6 and added to Solaris 11.3.
+*/
+class Getentropy final : public Entropy_Source
+ {
+ public:
+ std::string name() const override { return "getentropy"; }
+ size_t poll(RandomNumberGenerator& rng) override;
+ };
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/entropy/getentropy/info.txt b/comm/third_party/botan/src/lib/entropy/getentropy/info.txt
new file mode 100644
index 0000000000..886e57151f
--- /dev/null
+++ b/comm/third_party/botan/src/lib/entropy/getentropy/info.txt
@@ -0,0 +1,11 @@
+<defines>
+ENTROPY_SRC_GETENTROPY -> 20170327
+</defines>
+
+<header:internal>
+getentropy.h
+</header:internal>
+
+<os_features>
+getentropy
+</os_features>
diff --git a/comm/third_party/botan/src/lib/entropy/info.txt b/comm/third_party/botan/src/lib/entropy/info.txt
new file mode 100644
index 0000000000..57f1930b99
--- /dev/null
+++ b/comm/third_party/botan/src/lib/entropy/info.txt
@@ -0,0 +1,7 @@
+<defines>
+ENTROPY_SOURCE -> 20151120
+</defines>
+
+<requires>
+rng
+</requires>
diff --git a/comm/third_party/botan/src/lib/entropy/proc_walk/info.txt b/comm/third_party/botan/src/lib/entropy/proc_walk/info.txt
new file mode 100644
index 0000000000..2bba7e276b
--- /dev/null
+++ b/comm/third_party/botan/src/lib/entropy/proc_walk/info.txt
@@ -0,0 +1,11 @@
+<defines>
+ENTROPY_SRC_PROC_WALKER -> 20131128
+</defines>
+
+<header:internal>
+proc_walk.h
+</header:internal>
+
+<os_features>
+posix1,proc_fs
+</os_features>
diff --git a/comm/third_party/botan/src/lib/entropy/proc_walk/proc_walk.cpp b/comm/third_party/botan/src/lib/entropy/proc_walk/proc_walk.cpp
new file mode 100644
index 0000000000..d780cbf739
--- /dev/null
+++ b/comm/third_party/botan/src/lib/entropy/proc_walk/proc_walk.cpp
@@ -0,0 +1,154 @@
+/*
+* Entropy source based on reading files in /proc on the assumption
+* that a remote attacker will have difficulty guessing some of them.
+*
+* (C) 1999-2008,2012 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/internal/proc_walk.h>
+#include <deque>
+
+#ifndef _POSIX_C_SOURCE
+ #define _POSIX_C_SOURCE 199309
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <fcntl.h>
+
+namespace Botan {
+
+namespace {
+
+class Directory_Walker final : public File_Descriptor_Source
+ {
+ public:
+ explicit Directory_Walker(const std::string& root) :
+ m_cur_dir(std::make_pair<DIR*, std::string>(nullptr, ""))
+ {
+ if(DIR* root_dir = ::opendir(root.c_str()))
+ m_cur_dir = std::make_pair(root_dir, root);
+ }
+
+ ~Directory_Walker()
+ {
+ if(m_cur_dir.first)
+ ::closedir(m_cur_dir.first);
+ }
+
+ int next_fd() override;
+ private:
+ std::pair<struct dirent*, std::string> get_next_dirent();
+
+ std::pair<DIR*, std::string> m_cur_dir;
+ std::deque<std::string> m_dirlist;
+ };
+
+std::pair<struct dirent*, std::string> Directory_Walker::get_next_dirent()
+ {
+ while(m_cur_dir.first)
+ {
+ if(struct dirent* dir = ::readdir(m_cur_dir.first))
+ return std::make_pair(dir, m_cur_dir.second);
+
+ ::closedir(m_cur_dir.first);
+ m_cur_dir = std::make_pair<DIR*, std::string>(nullptr, "");
+
+ while(!m_dirlist.empty() && !m_cur_dir.first)
+ {
+ const std::string next_dir_name = m_dirlist[0];
+ m_dirlist.pop_front();
+
+ if(DIR* next_dir = ::opendir(next_dir_name.c_str()))
+ m_cur_dir = std::make_pair(next_dir, next_dir_name);
+ }
+ }
+
+ return std::make_pair<struct dirent*, std::string>(nullptr, ""); // nothing left
+ }
+
+int Directory_Walker::next_fd()
+ {
+ while(true)
+ {
+ std::pair<struct dirent*, std::string> entry = get_next_dirent();
+
+ if(!entry.first)
+ break; // no more dirs
+
+ const std::string filename = entry.first->d_name;
+
+ if(filename == "." || filename == "..")
+ continue;
+
+ const std::string full_path = entry.second + "/" + filename;
+
+ struct stat stat_buf;
+ if(::lstat(full_path.c_str(), &stat_buf) == -1)
+ continue;
+
+ if(S_ISDIR(stat_buf.st_mode))
+ {
+ m_dirlist.push_back(full_path);
+ }
+ else if(S_ISREG(stat_buf.st_mode) && (stat_buf.st_mode & S_IROTH))
+ {
+ int fd = ::open(full_path.c_str(), O_RDONLY | O_NOCTTY);
+
+ if(fd >= 0)
+ return fd;
+ }
+ }
+
+ return -1;
+ }
+
+}
+
+size_t ProcWalking_EntropySource::poll(RandomNumberGenerator& rng)
+ {
+ const size_t MAX_FILES_READ_PER_POLL = 2048;
+
+ lock_guard_type<mutex_type> lock(m_mutex);
+
+ if(!m_dir)
+ m_dir.reset(new Directory_Walker(m_path));
+
+ m_buf.resize(4096);
+
+ size_t bits = 0;
+
+ for(size_t i = 0; i != MAX_FILES_READ_PER_POLL; ++i)
+ {
+ int fd = m_dir->next_fd();
+
+ // If we've exhaused this walk of the directory, halt the poll
+ if(fd == -1)
+ {
+ m_dir.reset();
+ break;
+ }
+
+ ssize_t got = ::read(fd, m_buf.data(), m_buf.size());
+ ::close(fd);
+
+ if(got > 0)
+ {
+ rng.add_entropy(m_buf.data(), static_cast<size_t>(got));
+
+ // Conservative estimate of 4 bits per file
+ bits += 4;
+ }
+
+ if(bits > 128)
+ break;
+ }
+
+ return bits;
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/entropy/proc_walk/proc_walk.h b/comm/third_party/botan/src/lib/entropy/proc_walk/proc_walk.h
new file mode 100644
index 0000000000..4c5013d29c
--- /dev/null
+++ b/comm/third_party/botan/src/lib/entropy/proc_walk/proc_walk.h
@@ -0,0 +1,45 @@
+/*
+* File Tree Walking EntropySource
+* (C) 1999-2008 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_ENTROPY_SRC_PROC_WALK_H_
+#define BOTAN_ENTROPY_SRC_PROC_WALK_H_
+
+#include <botan/entropy_src.h>
+#include <botan/mutex.h>
+
+namespace Botan {
+
+class File_Descriptor_Source
+ {
+ public:
+ virtual int next_fd() = 0;
+ virtual ~File_Descriptor_Source() = default;
+ };
+
+/**
+* File Tree Walking Entropy Source
+*/
+class ProcWalking_EntropySource final : public Entropy_Source
+ {
+ public:
+ std::string name() const override { return "proc_walk"; }
+
+ size_t poll(RandomNumberGenerator& rng) override;
+
+ explicit ProcWalking_EntropySource(const std::string& root_dir) :
+ m_path(root_dir), m_dir(nullptr) {}
+
+ private:
+ const std::string m_path;
+ mutex_type m_mutex;
+ std::unique_ptr<File_Descriptor_Source> m_dir;
+ secure_vector<uint8_t> m_buf;
+ };
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/entropy/rdseed/info.txt b/comm/third_party/botan/src/lib/entropy/rdseed/info.txt
new file mode 100644
index 0000000000..ee822ad7c0
--- /dev/null
+++ b/comm/third_party/botan/src/lib/entropy/rdseed/info.txt
@@ -0,0 +1,19 @@
+<defines>
+ENTROPY_SRC_RDSEED -> 20151218
+</defines>
+
+<isa>
+rdseed
+sse2 # for mm_pause see #2139
+</isa>
+
+<header:internal>
+rdseed.h
+</header:internal>
+
+<cc>
+gcc
+clang
+icc
+msvc
+</cc>
diff --git a/comm/third_party/botan/src/lib/entropy/rdseed/rdseed.cpp b/comm/third_party/botan/src/lib/entropy/rdseed/rdseed.cpp
new file mode 100644
index 0000000000..1830edf9de
--- /dev/null
+++ b/comm/third_party/botan/src/lib/entropy/rdseed/rdseed.cpp
@@ -0,0 +1,97 @@
+/*
+* Entropy Source Using Intel's rdseed instruction
+* (C) 2015 Daniel Neus
+* (C) 2015,2019 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/internal/rdseed.h>
+#include <botan/cpuid.h>
+
+#include <immintrin.h>
+
+namespace Botan {
+
+namespace {
+
+BOTAN_FUNC_ISA("rdseed")
+bool read_rdseed(secure_vector<uint32_t>& seed)
+ {
+ /*
+ * RDSEED is not guaranteed to generate an output within any specific number
+ * of attempts. However in testing on a Skylake system, with all hyperthreads
+ * occupied in tight RDSEED loops, RDSEED will still usually succeed in under
+ * 150 attempts. The maximum ever seen was 230 attempts until success. When
+ * idle, RDSEED usually succeeds in 1 or 2 attempts.
+ *
+ * We set an upper bound of 512 attempts, because it is possible that due
+ * to firmware issue RDSEED is simply broken and never succeeds. We do not
+ * want to loop forever in that case. If we exceed that limit, then we assume
+ * the hardware is actually just broken, and stop the poll.
+ */
+ const size_t RDSEED_RETRIES = 512;
+
+ for(size_t i = 0; i != RDSEED_RETRIES; ++i)
+ {
+ uint32_t r = 0;
+ int cf = 0;
+
+#if defined(BOTAN_USE_GCC_INLINE_ASM)
+ asm("rdseed %0; adcl $0,%1" :
+ "=r" (r), "=r" (cf) : "0" (r), "1" (cf) : "cc");
+#else
+ cf = _rdseed32_step(&r);
+#endif
+
+ if(1 == cf)
+ {
+ seed.push_back(r);
+ return true;
+ }
+
+ // Intel suggests pausing if RDSEED fails.
+ _mm_pause();
+ }
+
+ return false; // failed to produce an output after many attempts
+ }
+
+}
+
+size_t Intel_Rdseed::poll(RandomNumberGenerator& rng)
+ {
+ const size_t RDSEED_BYTES = 1024;
+ static_assert(RDSEED_BYTES % 4 == 0, "Bad RDSEED configuration");
+
+ if(CPUID::has_rdseed())
+ {
+ secure_vector<uint32_t> seed;
+ seed.reserve(RDSEED_BYTES / 4);
+
+ for(size_t p = 0; p != RDSEED_BYTES / 4; ++p)
+ {
+ /*
+ If at any point we exceed our retry count, we stop the entire seed
+ gathering process. This situation will only occur in situations of
+ extremely high RDSEED utilization. If RDSEED is currently so highly
+ contended, then the rest of the poll is likely to also face contention and
+ it is better to quit now rather than (presumably) face very high retry
+ times for the rest of the poll.
+ */
+ if(!read_rdseed(seed))
+ break;
+ }
+
+ if(seed.size() > 0)
+ {
+ rng.add_entropy(reinterpret_cast<const uint8_t*>(seed.data()),
+ seed.size() * sizeof(uint32_t));
+ }
+ }
+
+ // RDSEED is used but not trusted
+ return 0;
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/entropy/rdseed/rdseed.h b/comm/third_party/botan/src/lib/entropy/rdseed/rdseed.h
new file mode 100644
index 0000000000..da94bc0a10
--- /dev/null
+++ b/comm/third_party/botan/src/lib/entropy/rdseed/rdseed.h
@@ -0,0 +1,28 @@
+/*
+* Entropy Source Using Intel's rdseed instruction
+* (C) 2015 Jack Lloyd, Daniel Neus
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_ENTROPY_SRC_RDSEED_H_
+#define BOTAN_ENTROPY_SRC_RDSEED_H_
+
+#include <botan/entropy_src.h>
+
+namespace Botan {
+
+/**
+* Entropy source using the rdseed instruction first introduced on
+* Intel's Broadwell architecture.
+*/
+class Intel_Rdseed final : public Entropy_Source
+ {
+ public:
+ std::string name() const override { return "rdseed"; }
+ size_t poll(RandomNumberGenerator& rng) override;
+ };
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/entropy/win32_stats/es_win32.cpp b/comm/third_party/botan/src/lib/entropy/win32_stats/es_win32.cpp
new file mode 100644
index 0000000000..3a175bf19d
--- /dev/null
+++ b/comm/third_party/botan/src/lib/entropy/win32_stats/es_win32.cpp
@@ -0,0 +1,59 @@
+/*
+* (C) 1999-2009,2016,2020 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/internal/es_win32.h>
+
+#define NOMINMAX 1
+#define _WINSOCKAPI_ // stop windows.h including winsock.h
+#include <windows.h>
+
+namespace Botan {
+
+size_t Win32_EntropySource::poll(RandomNumberGenerator& rng)
+ {
+ rng.add_entropy_T(::GetTickCount());
+ rng.add_entropy_T(::GetMessagePos());
+ rng.add_entropy_T(::GetMessageTime());
+ rng.add_entropy_T(::GetInputState());
+
+ rng.add_entropy_T(::GetCurrentProcessId());
+ rng.add_entropy_T(::GetCurrentThreadId());
+
+ SYSTEM_INFO sys_info;
+ ::GetSystemInfo(&sys_info);
+ rng.add_entropy_T(sys_info);
+
+ MEMORYSTATUSEX mem_info;
+ ::GlobalMemoryStatusEx(&mem_info);
+ rng.add_entropy_T(mem_info);
+
+ POINT point;
+ ::GetCursorPos(&point);
+ rng.add_entropy_T(point);
+
+ ::GetCaretPos(&point);
+ rng.add_entropy_T(point);
+
+ /*
+ Potential other sources to investigate
+
+ GetProductInfo
+ GetComputerNameExA
+ GetSystemFirmwareTable
+ GetVersionExA
+ GetProcessorSystemCycleTime
+ GetProcessHandleCount(GetCurrentProcess())
+ GetThreadTimes(GetCurrentThread())
+ QueryThreadCycleTime
+ QueryIdleProcessorCycleTime
+ QueryUnbiasedInterruptTime
+ */
+
+ // We assume all of the above is basically junk
+ return 0;
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/entropy/win32_stats/es_win32.h b/comm/third_party/botan/src/lib/entropy/win32_stats/es_win32.h
new file mode 100644
index 0000000000..2b11ee0801
--- /dev/null
+++ b/comm/third_party/botan/src/lib/entropy/win32_stats/es_win32.h
@@ -0,0 +1,27 @@
+/*
+* Win32 EntropySource
+* (C) 1999-2009 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_ENTROPY_SRC_WIN32_H_
+#define BOTAN_ENTROPY_SRC_WIN32_H_
+
+#include <botan/entropy_src.h>
+
+namespace Botan {
+
+/**
+* Win32 Entropy Source
+*/
+class Win32_EntropySource final : public Entropy_Source
+ {
+ public:
+ std::string name() const override { return "system_stats"; }
+ size_t poll(RandomNumberGenerator& rng) override;
+ };
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/entropy/win32_stats/info.txt b/comm/third_party/botan/src/lib/entropy/win32_stats/info.txt
new file mode 100644
index 0000000000..1123403b5d
--- /dev/null
+++ b/comm/third_party/botan/src/lib/entropy/win32_stats/info.txt
@@ -0,0 +1,15 @@
+<defines>
+ENTROPY_SRC_WIN32 -> 20200209
+</defines>
+
+<header:internal>
+es_win32.h
+</header:internal>
+
+<os_features>
+win32
+</os_features>
+
+<libs>
+windows -> user32
+</libs>