diff options
author | Jack Lloyd <[email protected]> | 2016-06-30 13:15:30 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2016-07-17 10:43:40 -0400 |
commit | 93922f20f04058ec624f7db3c74d8aa5a3d06440 (patch) | |
tree | 81144cfacced43c68c4385683ee0c123a1987042 /src/lib/entropy/dev_random/dev_random.cpp | |
parent | 4c5847412d41756aab738a3746666cfaffe5d4af (diff) |
Add Stateful_RNG
Handles fork checking for HMAC_RNG and HMAC_DRBG
AutoSeeded_RNG change - switch to HMAC_DRBG as default.
Start removing the io buffer from entropy poller.
Update default RNG poll bits to 256.
Fix McEliece test, was using wrong RNG API.
Update docs.
Diffstat (limited to 'src/lib/entropy/dev_random/dev_random.cpp')
-rw-r--r-- | src/lib/entropy/dev_random/dev_random.cpp | 75 |
1 files changed, 52 insertions, 23 deletions
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); + } + } } } } |