diff options
Diffstat (limited to 'src/lib/entropy')
-rw-r--r-- | src/lib/entropy/darwin_secrandom/darwin_secrandom.cpp | 6 | ||||
-rw-r--r-- | src/lib/entropy/darwin_secrandom/darwin_secrandom.h | 2 | ||||
-rw-r--r-- | src/lib/entropy/dev_random/dev_random.cpp | 75 | ||||
-rw-r--r-- | src/lib/entropy/dev_random/dev_random.h | 6 |
4 files changed, 61 insertions, 28 deletions
diff --git a/src/lib/entropy/darwin_secrandom/darwin_secrandom.cpp b/src/lib/entropy/darwin_secrandom/darwin_secrandom.cpp index 0a6b85955..7dde17155 100644 --- a/src/lib/entropy/darwin_secrandom/darwin_secrandom.cpp +++ b/src/lib/entropy/darwin_secrandom/darwin_secrandom.cpp @@ -16,11 +16,11 @@ namespace Botan { */ void Darwin_SecRandom::poll(Entropy_Accumulator& accum) { - secure_vector<byte>& buf = accum.get_io_buf(BOTAN_SYSTEM_RNG_POLL_REQUEST); + m_io_buf.resize(BOTAN_SYSTEM_RNG_POLL_REQUEST); - if(0 == SecRandomCopyBytes(kSecRandomDefault, buf.size(), buf.data())) + if(0 == SecRandomCopyBytes(kSecRandomDefault, m_io_buf.size(), m_io_buf.data())) { - accum.add(buf.data(), buf.size(), BOTAN_ENTROPY_ESTIMATE_STRONG_RNG); + accum.add(m_io_buf.data(), m_io_buf.size(), BOTAN_ENTROPY_ESTIMATE_STRONG_RNG); } } diff --git a/src/lib/entropy/darwin_secrandom/darwin_secrandom.h b/src/lib/entropy/darwin_secrandom/darwin_secrandom.h index 09cdc208d..267d177f0 100644 --- a/src/lib/entropy/darwin_secrandom/darwin_secrandom.h +++ b/src/lib/entropy/darwin_secrandom/darwin_secrandom.h @@ -21,6 +21,8 @@ class Darwin_SecRandom final : public Entropy_Source std::string name() const override { return "darwin_secrandom"; } void poll(Entropy_Accumulator& accum) override; + private: + secure_vector<uint8_t> m_io_buf; }; } diff --git a/src/lib/entropy/dev_random/dev_random.cpp b/src/lib/entropy/dev_random/dev_random.cpp index aca161d64..ff746f34e 100644 --- a/src/lib/entropy/dev_random/dev_random.cpp +++ b/src/lib/entropy/dev_random/dev_random.cpp @@ -6,6 +6,7 @@ */ #include <botan/internal/dev_random.h> +#include <botan/exceptn.h> #include <sys/types.h> #include <sys/select.h> @@ -31,15 +32,39 @@ Device_EntropySource::Device_EntropySource(const std::vector<std::string>& fsnam const int flags = O_RDONLY | O_NONBLOCK | O_NOCTTY; + m_max_fd = 0; + for(auto fsname : fsnames) { - fd_type fd = ::open(fsname.c_str(), flags); + int fd = ::open(fsname.c_str(), flags); - if(fd >= 0 && fd < FD_SETSIZE) - m_devices.push_back(fd); - else if(fd >= 0) - ::close(fd); + if(fd > 0) + { + if(fd > FD_SETSIZE) + { + ::close(fd); + throw Exception("Open of OS RNG succeeded but fd is too large for fd_set"); + } + + m_dev_fds.push_back(fd); + m_max_fd = std::max(m_max_fd, fd); + } + else + { + /* + 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 Exception("Opening OS RNG device failed with errno " + + std::to_string(errno)); + } + } } + + m_io_buf.resize(BOTAN_SYSTEM_RNG_POLL_REQUEST); } /** @@ -47,8 +72,11 @@ Device_EntropySource destructor: close all open devices */ Device_EntropySource::~Device_EntropySource() { - for(size_t i = 0; i != m_devices.size(); ++i) - ::close(m_devices[i]); + for(int fd : m_dev_fds) + { + // ignoring return value here, can't throw in destructor anyway + ::close(fd); + } } /** @@ -56,35 +84,36 @@ Device_EntropySource::~Device_EntropySource() */ void Device_EntropySource::poll(Entropy_Accumulator& accum) { - if(m_devices.empty()) + if(m_dev_fds.empty()) return; - fd_type max_fd = m_devices[0]; fd_set read_set; FD_ZERO(&read_set); - for(size_t i = 0; i != m_devices.size(); ++i) + + for(int dev_fd : m_dev_fds) { - FD_SET(m_devices[i], &read_set); - max_fd = std::max(m_devices[i], max_fd); + FD_SET(dev_fd, &read_set); } 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(max_fd + 1, &read_set, nullptr, nullptr, &timeout) < 0) - return; - - secure_vector<byte>& buf = accum.get_io_buf(BOTAN_SYSTEM_RNG_POLL_REQUEST); - - for(size_t i = 0; i != m_devices.size(); ++i) + if(::select(m_max_fd + 1, &read_set, nullptr, nullptr, &timeout) > 0) { - if(FD_ISSET(m_devices[i], &read_set)) + for(int dev_fd : m_dev_fds) { - const ssize_t got = ::read(m_devices[i], buf.data(), buf.size()); - if(got > 0) - accum.add(buf.data(), got, BOTAN_ENTROPY_ESTIMATE_STRONG_RNG); + if(FD_ISSET(dev_fd, &read_set)) + { + const ssize_t got = ::read(dev_fd, m_io_buf.data(), m_io_buf.size()); + + if(got > 0) + { + accum.add(m_io_buf.data(), + static_cast<size_t>(got), + BOTAN_ENTROPY_ESTIMATE_STRONG_RNG); + } + } } } } diff --git a/src/lib/entropy/dev_random/dev_random.h b/src/lib/entropy/dev_random/dev_random.h index 1f29b2f64..05b36f3eb 100644 --- a/src/lib/entropy/dev_random/dev_random.h +++ b/src/lib/entropy/dev_random/dev_random.h @@ -25,10 +25,12 @@ class Device_EntropySource final : public Entropy_Source void poll(Entropy_Accumulator& accum) override; Device_EntropySource(const std::vector<std::string>& fsnames); + ~Device_EntropySource(); private: - typedef int fd_type; - std::vector<fd_type> m_devices; + secure_vector<uint8_t> m_io_buf; + std::vector<int> m_dev_fds; + int m_max_fd; }; } |