]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/auth/Crypto.cc
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / auth / Crypto.cc
index 8b355bf1142301c112509334876102f8f79cab66..b88b6939e07f1be73e06e957696106b7229bf417 100644 (file)
 
 #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());
   }
@@ -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());
@@ -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
@@ -253,6 +288,8 @@ public:
     // let's pad the data
     std::uint8_t pad_len = out_tmp.length() - in.length();
     ceph::bufferptr pad_buf{pad_len};
+    // FIPS zeroization audit 20191115: this memset is not intended to
+    // wipe out a secret after use.
     memset(pad_buf.c_str(), pad_len, pad_len);
 
     // form contiguous buffer for block cipher. The ctor copies shallowly.
@@ -328,6 +365,8 @@ public:
 
     std::array<unsigned char, AES_BLOCK_LEN> last_block;
     memcpy(last_block.data(), in.buf + in.length - tail_len, tail_len);
+    // FIPS zeroization audit 20191115: this memset is not intended to
+    // wipe out a secret after use.
     memset(last_block.data() + tail_len, pad_len, pad_len);
 
     // need a local copy because AES_cbc_encrypt takes `iv` as non-const.