]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
auth: extend CryptoKey with no-bl encrypt/decrypt.
authorRadoslaw Zarzynski <rzarzyns@redhat.com>
Thu, 19 Apr 2018 23:43:57 +0000 (01:43 +0200)
committerRadoslaw Zarzynski <rzarzyns@redhat.com>
Fri, 18 May 2018 14:49:07 +0000 (10:49 -0400)
Signed-off-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
src/auth/Crypto.cc
src/auth/Crypto.h
src/auth/cephx/CephxSessionHandler.cc

index 8d398f2df9b9edae7120b794d6ba565636d2b322..c9ab4f4f967144e32dcc26653aa3bf35b33643e9 100644 (file)
@@ -73,10 +73,69 @@ void CryptoRandom::get_bytes(char *buf, int len)
 #endif
 
 
+// ---------------------------------------------------
+// fallback implementation of the bufferlist-free
+// interface.
+
+std::size_t CryptoKeyHandler::encrypt(
+  const CryptoKeyHandler::in_slice_t& in,
+  const CryptoKeyHandler::out_slice_t& out) const
+{
+  ceph::bufferptr inptr(reinterpret_cast<const char*>(in.buf), in.length);
+  ceph::bufferlist plaintext;
+  plaintext.append(std::move(inptr));
+
+  ceph::bufferlist ciphertext;
+  std::string error;
+  const int ret = encrypt(plaintext, ciphertext, &error);
+  if (ret != 0 || !error.empty()) {
+    throw std::runtime_error(std::move(error));
+  }
+
+  // we need to specify the template parameter explicitly as ::length()
+  // returns unsigned int, not size_t.
+  const auto todo_len = \
+    std::min<std::size_t>(ciphertext.length(), out.max_length);
+  memcpy(out.buf, ciphertext.c_str(), todo_len);
+
+  return todo_len;
+}
+
+std::size_t CryptoKeyHandler::decrypt(
+  const CryptoKeyHandler::in_slice_t& in,
+  const CryptoKeyHandler::out_slice_t& out) const
+{
+  ceph::bufferptr inptr(reinterpret_cast<const char*>(in.buf), in.length);
+  ceph::bufferlist ciphertext;
+  ciphertext.append(std::move(inptr));
+
+  ceph::bufferlist plaintext;
+  std::string error;
+  const int ret = decrypt(ciphertext, plaintext, &error);
+  if (ret != 0 || !error.empty()) {
+    throw std::runtime_error(std::move(error));
+  }
+
+  // we need to specify the template parameter explicitly as ::length()
+  // returns unsigned int, not size_t.
+  const auto todo_len = \
+    std::min<std::size_t>(plaintext.length(), out.max_length);
+  memcpy(out.buf, plaintext.c_str(), todo_len);
+
+  return todo_len;
+}
+
 // ---------------------------------------------------
 
 class CryptoNoneKeyHandler : public CryptoKeyHandler {
 public:
+  CryptoNoneKeyHandler()
+    : CryptoKeyHandler(CryptoKeyHandler::BLOCK_SIZE_0B()) {
+  }
+
+  using CryptoKeyHandler::encrypt;
+  using CryptoKeyHandler::decrypt;
+
   int encrypt(const bufferlist& in,
               bufferlist& out, std::string *error) const override {
     out = in;
@@ -128,12 +187,15 @@ public:
 # define AES_KEY_LEN   16
 # define AES_BLOCK_LEN   16
 
-
 class CryptoAESKeyHandler : public CryptoKeyHandler {
   AES_KEY enc_key;
   AES_KEY dec_key;
 
 public:
+  CryptoAESKeyHandler()
+    : CryptoKeyHandler(CryptoKeyHandler::BLOCK_SIZE_16B()) {
+  }
+
   int init(const bufferptr& s, ostringstream& err) {
     secret = s;
 
@@ -227,6 +289,15 @@ public:
 
     return 0;
   }
+
+  std::size_t encrypt(const in_slice_t& in,
+                     const out_slice_t& out) const override {
+    return 0;
+  }
+  std::size_t decrypt(const in_slice_t& in,
+                     const out_slice_t& out) const override {
+    return 0;
+  }
 };
 
 #else
index a0cb5725652ea4e2142518eaa52e3170ac896d8b..fa1941233a024897027498439e85981e48a31c00 100644 (file)
@@ -44,7 +44,29 @@ class CryptoRandom {
  */
 class CryptoKeyHandler {
 public:
-  bufferptr secret;
+  // The maximum size of a single block for all descendants of the class.
+  static constexpr std::size_t MAX_BLOCK_SIZE {16};
+
+  // A descendant pick-ups one from these and passes it to the ctor template.
+  typedef std::integral_constant<std::size_t,  0> BLOCK_SIZE_0B;
+  typedef std::integral_constant<std::size_t, 16> BLOCK_SIZE_16B;
+
+  struct in_slice_t {
+    const std::size_t length;
+    const unsigned char* const buf;
+  };
+
+  struct out_slice_t {
+    const std::size_t max_length;
+    unsigned char* const buf;
+  };
+
+  ceph::bufferptr secret;
+
+  template <class BlockSizeT>
+  CryptoKeyHandler(BlockSizeT) {
+    static_assert(BlockSizeT::value <= MAX_BLOCK_SIZE);
+  }
 
   virtual ~CryptoKeyHandler() {}
 
@@ -52,6 +74,13 @@ public:
                       bufferlist& out, std::string *error) const = 0;
   virtual int decrypt(const bufferlist& in,
                       bufferlist& out, std::string *error) const = 0;
+
+  // TODO: provide nullptr in the out::buf to get/estimate size requirements?
+  // Or maybe dedicated methods?
+  virtual std::size_t encrypt(const in_slice_t& in,
+                             const out_slice_t& out) const;
+  virtual std::size_t decrypt(const in_slice_t& in,
+                             const out_slice_t& out) const;
 };
 
 /*
@@ -127,6 +156,24 @@ public:
     return ckh->decrypt(in, out, error);
   }
 
+  using in_slice_t = CryptoKeyHandler::in_slice_t;
+  using out_slice_t = CryptoKeyHandler::out_slice_t;
+
+  std::size_t encrypt(CephContext*, const in_slice_t& in,
+                     const out_slice_t& out) {
+    assert(ckh);
+    return ckh->encrypt(in, out);
+  }
+  std::size_t decrypt(CephContext*, const in_slice_t& in,
+                     const out_slice_t& out) {
+    assert(ckh);
+    return ckh->encrypt(in, out);
+  }
+
+  static constexpr std::size_t get_max_outbuf_size(std::size_t want_size) {
+    return want_size + CryptoKeyHandler::MAX_BLOCK_SIZE;
+  }
+
   void to_str(std::string& s) const;
 };
 WRITE_CLASS_ENCODER(CryptoKey)
index f9589a06e5dabdccc4d8103bc18d17cae5542105..f2e332b41b309f2584b50b20f06b595fd52e047a 100644 (file)
@@ -45,17 +45,26 @@ int CephxSessionHandler::_calc_signature(Message *m, uint64_t *psig)
     mswab<uint32_t>(header.crc), mswab<uint32_t>(footer.front_crc),
     mswab<uint32_t>(footer.middle_crc), mswab<uint32_t>(footer.data_crc)
   };
-  bufferlist bl_plaintext;
-  bl_plaintext.append(buffer::create_static(sizeof(sigblock), (char*)&sigblock));
 
-  bufferlist bl_ciphertext;
-  if (key.encrypt(cct, bl_plaintext, bl_ciphertext, NULL) < 0) {
+  char exp_buf[CryptoKey::get_max_outbuf_size(sizeof(sigblock))];
+
+  try {
+    const CryptoKey::in_slice_t in {
+      sizeof(sigblock),
+      reinterpret_cast<const unsigned char*>(&sigblock)
+    };
+    const CryptoKey::out_slice_t out {
+      sizeof(exp_buf),
+      reinterpret_cast<unsigned char*>(&exp_buf)
+    };
+
+    key.encrypt(cct, in, out);
+  } catch (std::exception& e) {
     lderr(cct) << __func__ << " failed to encrypt signature block" << dendl;
     return -1;
   }
 
-  auto ci = bl_ciphertext.cbegin();
-  decode(*psig, ci);
+  *psig = *reinterpret_cast<__le64*>(exp_buf);
 
   ldout(cct, 10) << __func__ << " seq " << m->get_seq()
                 << " front_crc_ = " << footer.front_crc