diff options
Diffstat (limited to 'src/lib/rng/system_rng/system_rng.cpp')
-rw-r--r-- | src/lib/rng/system_rng/system_rng.cpp | 76 |
1 files changed, 59 insertions, 17 deletions
diff --git a/src/lib/rng/system_rng/system_rng.cpp b/src/lib/rng/system_rng/system_rng.cpp index 81e235a8c..b6440d968 100644 --- a/src/lib/rng/system_rng/system_rng.cpp +++ b/src/lib/rng/system_rng/system_rng.cpp @@ -28,32 +28,23 @@ namespace Botan { namespace { -class System_RNG_Impl : public RandomNumberGenerator +class System_RNG_Impl final : public RandomNumberGenerator { public: System_RNG_Impl(); ~System_RNG_Impl(); - void randomize(byte buf[], size_t len) override; - bool is_seeded() const override { return true; } + void clear() override {} - std::string name() const override { return "system"; } - size_t reseed_with_sources(Entropy_Sources&, - size_t /*poll_bits*/, - std::chrono::milliseconds /*timeout*/) override - { - // We ignore it and assert the PRNG is seeded. - // TODO: could poll and write it to /dev/urandom to help seed it - return 0; - } + void randomize(Botan::byte out[], size_t len) override; - void add_entropy(const byte[], size_t) override - { - } - private: + void add_entropy(const byte in[], size_t length) override; + + std::string name() const override; + private: #if defined(BOTAN_TARGET_OS_HAS_CRYPTGENRANDOM) HCRYPTPROV m_prov; #else @@ -61,6 +52,15 @@ class System_RNG_Impl : public RandomNumberGenerator #endif }; +std::string System_RNG_Impl::name() const + { +#if defined(BOTAN_TARGET_OS_HAS_CRYPTGENRANDOM) + return "cryptoapi"; +#else + return BOTAN_SYSTEM_RNG_DEVICE; +#endif + } + System_RNG_Impl::System_RNG_Impl() { #if defined(BOTAN_TARGET_OS_HAS_CRYPTGENRANDOM) @@ -74,7 +74,7 @@ System_RNG_Impl::System_RNG_Impl() #define O_NOCTTY 0 #endif - m_fd = ::open(BOTAN_SYSTEM_RNG_DEVICE, O_RDONLY | O_NOCTTY); + m_fd = ::open(BOTAN_SYSTEM_RNG_DEVICE, O_RDWR | O_NOCTTY); if(m_fd < 0) throw Exception("System_RNG failed to open RNG device"); #endif @@ -90,6 +90,48 @@ System_RNG_Impl::~System_RNG_Impl() #endif } +void System_RNG_Impl::add_entropy(const byte input[], size_t len) + { +#if defined(BOTAN_TARGET_OS_HAS_CRYPTGENRANDOM) + /* + There is no explicit ConsumeRandom, but all values provided in + the call are incorporated into the state. + + TODO: figure out a way to avoid this copy. Byte at a time updating + seems worse than the allocation. + + for(size_t i = 0; i != len; ++i) + { + byte b = input[i]; + ::CryptGenRandom(m_prov, 1, &b); + } + */ + + if(len > 0) + { + secure_vector<byte> buf(input, input + len); + ::CryptGenRandom(m_prov, static_cast<DWORD>(buf.size()), buf.data()); + } +#else + while(len) + { + ssize_t got = ::write(m_fd, input, len); + + if(got < 0) + { + if(errno == EINTR) + continue; + + // maybe just ignore failure here and return? + throw Exception("System_RNG write failed error " + std::to_string(errno)); + } + + input += got; + len -= got; + } +#endif + } + void System_RNG_Impl::randomize(byte buf[], size_t len) { #if defined(BOTAN_TARGET_OS_HAS_CRYPTGENRANDOM) |