diff --git a/src/system/linux/system/urandom.hpp b/src/system/linux/system/urandom.hpp index 1de0d2d6f7..b68660bbf7 100644 --- a/src/system/linux/system/urandom.hpp +++ b/src/system/linux/system/urandom.hpp @@ -9,55 +9,36 @@ SPDX-License-Identifier: GPL-2.0-or-later #include "core/error.hpp" #include "utils/log.hpp" #include "utils/random.hpp" -#include "utils/sugar/unique_fd.hpp" -#include -#include - -#include +#include class URandom final : public Random { - unique_fd ufd; - public: - URandom() - : ufd(open("/dev/urandom", O_RDONLY)) - { - if (ufd.is_open()) { - LOG(LOG_INFO, "using /dev/urandom as random source"); - } - else { - LOG(LOG_INFO, "access to /dev/urandom failed: %s", strerror(errno)); - - ufd.reset(open("/dev/random", O_RDONLY)); - if (ufd.is_open()) { - LOG(LOG_INFO, "using /dev/random as random source"); - } - else { - LOG(LOG_ERR, "random source failed to provide random data : couldn't open device"); - throw Error(ERR_RANDOM_SOURCE_FAILED); - } - } - } - void random(writable_bytes_view buf) override { - // TODO This is basically a blocking read, we should provide timeout management and behaviour uint8_t* data = buf.data(); size_t len = buf.size(); while (len) { - ssize_t ret = ::read(ufd.fd(), data, len); - if (REDEMPTION_UNLIKELY(ret <= 0)) { +#if defined(__sun) && defined(__SVR4) + /* On Solaris, getrandom() is limited to returning up to 1024 bytes. */ + size_t len_max = 1024; +#else + size_t len_max = LONG_MAX; +#endif + // TODO This is basically a blocking read, we should provide timeout management and behaviour + ssize_t n = getrandom(data, len < len_max ? len : len_max, 0); + if (REDEMPTION_UNLIKELY(n < 0)) { if (errno == EINTR) { continue; } + // ignore errno == EAGAIN because GRND_NONBLOCK flag is not used LOG(LOG_ERR, "random source failed to provide random data [%s]", strerror(errno)); throw Error(ERR_RANDOM_SOURCE_FAILED); } - data += ret; - len -= ret; + data += n; + len -= n; } } };