#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;
# 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;
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
*/
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() {}
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;
};
/*
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)
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