// devrandom - RNG operations based on /dev/random
//
#include <Security/devrandom.h>
+#include <Security/logging.h>
+
+using namespace UnixPlusPlus;
namespace Security {
//
-// DevRandomGenerator objects immediately open their file descriptors
+// The common (shared) open file descriptor to /dev/random
+//
+ModuleNexus<DevRandomGenerator::Readonly> DevRandomGenerator::mReader;
+ModuleNexus<DevRandomGenerator::Writable> DevRandomGenerator::mWriter;
+
+
+//
+// In the current implementation, opening the file descriptor is deferred.
//
DevRandomGenerator::DevRandomGenerator(bool writable)
{
- mDevRandom.open("/dev/random", writable ? O_RDWR : O_RDONLY);
}
//
void DevRandomGenerator::random(void *data, size_t length)
{
- mDevRandom.read(data, length);
+ try {
+ size_t bytesRead = mReader().read(data, length);
+ if (bytesRead != length) { // short read (shouldn't happen)
+ Syslog::error("DevRandomGenerator: wanted %ld got %ld bytes",
+ length, bytesRead);
+ UnixError::throwMe(EIO);
+ }
+ } catch(const UnixError &uerr) {
+ Syslog::error("DevRandomGenerator: error %d reading /dev/random",
+ uerr.error);
+ throw;
+ }
}
//
void DevRandomGenerator::addEntropy(const void *data, size_t length)
{
- mDevRandom.write(data, length);
+ if (mWriter().write(data, length) != length)
+ UnixError::throwMe(EIO); // short write (shouldn't happen)
}