From: Radoslaw Zarzynski Date: Thu, 19 Apr 2018 23:43:57 +0000 (+0200) Subject: auth: extend CryptoKey with no-bl encrypt/decrypt. X-Git-Tag: v13.2.0~12^2~4 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=70e97ac3e9a8d2902463b894c8a53a9ddf4b86d1;p=ceph.git auth: extend CryptoKey with no-bl encrypt/decrypt. Signed-off-by: Radoslaw Zarzynski (cherry picked from commit b5acef206c94142464f7ff314bb11c843c5420e8) --- diff --git a/src/auth/Crypto.cc b/src/auth/Crypto.cc index 54a194553481..bf91acdd38a4 100644 --- a/src/auth/Crypto.cc +++ b/src/auth/Crypto.cc @@ -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(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(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(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(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 diff --git a/src/auth/Crypto.h b/src/auth/Crypto.h index 318a4bd3a273..533c747cfe5f 100644 --- a/src/auth/Crypto.h +++ b/src/auth/Crypto.h @@ -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 BLOCK_SIZE_0B; + typedef std::integral_constant 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 + 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) diff --git a/src/auth/cephx/CephxSessionHandler.cc b/src/auth/cephx/CephxSessionHandler.cc index 00b11338df5d..f2e332b41b30 100644 --- a/src/auth/cephx/CephxSessionHandler.cc +++ b/src/auth/cephx/CephxSessionHandler.cc @@ -45,17 +45,26 @@ int CephxSessionHandler::_calc_signature(Message *m, uint64_t *psig) mswab(header.crc), mswab(footer.front_crc), mswab(footer.middle_crc), mswab(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(&sigblock) + }; + const CryptoKey::out_slice_t out { + sizeof(exp_buf), + reinterpret_cast(&exp_buf) + }; + + key.encrypt(cct, in, out); + } catch (std::exception& e) { lderr(cct) << __func__ << " failed to encrypt signature block" << dendl; return -1; } - bufferlist::iterator ci = bl_ciphertext.begin(); - decode(*psig, ci); + *psig = *reinterpret_cast<__le64*>(exp_buf); ldout(cct, 10) << __func__ << " seq " << m->get_seq() << " front_crc_ = " << footer.front_crc