Skip to content

Commit

Permalink
Merge pull request #31301 from smithfarm/wip-42134-nautilus
Browse files Browse the repository at this point in the history
nautilus: core: auth/Crypto: fallback to /dev/urandom if getentropy() fails

Reviewed-by: Josh Durgin <jdurgin@redhat.com>
  • Loading branch information
yuriw committed Dec 18, 2019
2 parents 0244ad2 + b1d4498 commit afd25bc
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 7 deletions.
43 changes: 39 additions & 4 deletions src/auth/Crypto.cc
Expand Up @@ -41,12 +41,39 @@

#include <unistd.h>

CryptoRandom::CryptoRandom() : fd(0) {}
CryptoRandom::~CryptoRandom() = default;
static bool getentropy_works()
{
char buf;
auto ret = TEMP_FAILURE_RETRY(::getentropy(&buf, sizeof(buf)));
if (ret == 0) {
return true;
} else if (errno == ENOSYS || errno == EPERM) {
return false;
} else {
throw std::system_error(errno, std::system_category());
}
}

CryptoRandom::CryptoRandom() : fd(getentropy_works() ? -1 : open_urandom())
{}

CryptoRandom::~CryptoRandom()
{
if (fd >= 0) {
VOID_TEMP_FAILURE_RETRY(::close(fd));
}
}

void CryptoRandom::get_bytes(char *buf, int len)
{
auto ret = TEMP_FAILURE_RETRY(::getentropy(buf, len));
ssize_t ret = 0;
if (unlikely(fd >= 0)) {
ret = safe_read_exact(fd, buf, len);
} else {
// getentropy() reads up to 256 bytes
assert(len <= 256);
ret = TEMP_FAILURE_RETRY(::getentropy(buf, len));
}
if (ret < 0) {
throw std::system_error(errno, std::system_category());
}
Expand All @@ -56,7 +83,7 @@ void CryptoRandom::get_bytes(char *buf, int len)

// open /dev/urandom once on construction and reuse the fd for all reads
CryptoRandom::CryptoRandom()
: fd(TEMP_FAILURE_RETRY(::open("/dev/urandom", O_CLOEXEC|O_RDONLY)))
: fd{open_urandom()}
{
if (fd < 0) {
throw std::system_error(errno, std::system_category());
Expand All @@ -78,6 +105,14 @@ void CryptoRandom::get_bytes(char *buf, int len)

#endif

int CryptoRandom::open_urandom()
{
int fd = TEMP_FAILURE_RETRY(::open("/dev/urandom", O_CLOEXEC|O_RDONLY));
if (fd < 0) {
throw std::system_error(errno, std::system_category());
}
return fd;
}

// ---------------------------------------------------
// fallback implementation of the bufferlist-free
Expand Down
7 changes: 4 additions & 3 deletions src/auth/Crypto.h
Expand Up @@ -29,13 +29,14 @@ namespace ceph { class Formatter; }
* Random byte stream generator suitable for cryptographic use
*/
class CryptoRandom {
const int fd;
public:
public:
CryptoRandom(); // throws on failure
~CryptoRandom();

/// copy up to 256 random bytes into the given buffer. throws on failure
void get_bytes(char *buf, int len);
private:
static int open_urandom();
const int fd;
};

/*
Expand Down

0 comments on commit afd25bc

Please sign in to comment.