aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/entropy/dev_random/dev_random.cpp
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2016-08-31 12:58:58 -0400
committerJack Lloyd <[email protected]>2016-08-31 12:58:58 -0400
commitdfab07a7bc00dc00f98ab86c70d536306073f34f (patch)
treed3dbb140764f259c932171d6f229d033dee685ca /src/lib/entropy/dev_random/dev_random.cpp
parente29024608fca1b811aa72a7aafd930a42740b968 (diff)
parent1b9cf39063194fe91dc8e5d78f73d7251c5d16fc (diff)
Merge master into this branch, resolving conflicts with #457/#576
which recently landed on master.
Diffstat (limited to 'src/lib/entropy/dev_random/dev_random.cpp')
-rw-r--r--src/lib/entropy/dev_random/dev_random.cpp92
1 files changed, 62 insertions, 30 deletions
diff --git a/src/lib/entropy/dev_random/dev_random.cpp b/src/lib/entropy/dev_random/dev_random.cpp
index aca161d64..b51f19ecb 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,14 +32,36 @@ 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));
+ }
+ }
}
}
@@ -47,46 +70,55 @@ 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);
+ }
}
/**
* Gather entropy from a RNG device
*/
-void Device_EntropySource::poll(Entropy_Accumulator& accum)
+size_t Device_EntropySource::poll(RandomNumberGenerator& rng)
{
- if(m_devices.empty())
- return;
+ size_t bits = 0;
- 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)
+ if(m_dev_fds.size() > 0)
{
- FD_SET(m_devices[i], &read_set);
- max_fd = std::max(m_devices[i], max_fd);
- }
-
- struct ::timeval timeout;
+ fd_set read_set;
+ FD_ZERO(&read_set);
- timeout.tv_sec = (BOTAN_SYSTEM_RNG_POLL_TIMEOUT_MS / 1000);
- timeout.tv_usec = (BOTAN_SYSTEM_RNG_POLL_TIMEOUT_MS % 1000) * 1000;
+ for(int dev_fd : m_dev_fds)
+ {
+ FD_SET(dev_fd, &read_set);
+ }
- if(::select(max_fd + 1, &read_set, nullptr, nullptr, &timeout) < 0)
- return;
+ secure_vector<uint8_t> io_buf(BOTAN_SYSTEM_RNG_POLL_REQUEST);
- secure_vector<byte>& buf = accum.get_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;
- for(size_t i = 0; i != m_devices.size(); ++i)
- {
- if(FD_ISSET(m_devices[i], &read_set))
+ if(::select(m_max_fd + 1, &read_set, nullptr, nullptr, &timeout) > 0)
{
- 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);
+ 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;
}
}