Skip to content

Commit

Permalink
Merge PR ceph#26875 into nautilus
Browse files Browse the repository at this point in the history
* refs/pull/26875/head:
	common: implement HMACs on top of OpenSSL.
	msg/async, v2: switch the pre-auth mechanism to HMAC-SHA256.
	include/types: beef sha_digest_t up with encode and compare.
	auth: add hmac_sha256() to CryptoKey.
	msg/async, v2: introduce pre_auth exchanges with CRC32.
	msg/async, v2: introduce pre_auth buffers.
	msg/async, v2: rectify the encapsulation of rx_segments_{desc,data}.
	msg/async, v2: rework decoding of MessageFrame.
	msg/async, v2: limit the num_segments to non-empty segments.
	msg/async, v2: drop the bl onwire space optimization in ControlFrames.
	msg/async, v2: clean up ret handling in ProtocolV2::write().
	msg/async, v2: drop next_payload_len as we don't need anymore.
	msg/async, v2: drop temp_buffer and limitations driven by it.
	msg/async, v2: switch to rx_buffer_t entirely.
	msg/async, v2: rx continuations use buffer::ptr_node.
	msg/async, v2: use bptr continuation for segment reading.
	msg/async: introduce bptr-carrying continuations.
	msg/async: replace CONTINUATION_PARAM() with specialized types.
	msg/async, v2: ::_banner_exchange() takes CtRef instead of CtPtr.
	msg/async: avoid extra pointers in continuation definitions.
	msg/async, v2: dissect setting stream handlers into ::finish_auth().
	msg/async, v2: drop ceph_msg_header2 handling from ControlFrames.
	msg/async, v2: drop the SignedEncryptedFrame entirely.
	msg/async, v2: reintroduce segment aligment. It's compile-time now.
	msg/async, v2: generalize Frame about number of segments.
	msg/async, v2: rework and generalize Frame encryption.
	msg/async, v2: rework the class hierarchy - introduce MessageFrame.
	msg/async, v2: rework the class hierarchy - introduce ControlFrame.
	msg/async/ProtocolV2: remove obsolete AuthFlags

Reviewed-by: Sage Weil <[email protected]>
  • Loading branch information
liewegas committed Mar 14, 2019
2 parents bf53d69 + 9a391a2 commit d216aed
Show file tree
Hide file tree
Showing 11 changed files with 793 additions and 556 deletions.
14 changes: 14 additions & 0 deletions src/auth/Crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,20 @@ std::size_t CryptoKeyHandler::decrypt(
return todo_len;
}

sha256_digest_t CryptoKeyHandler::hmac_sha256(
const ceph::bufferlist& in) const
{
ceph::crypto::HMACSHA256 hmac((const unsigned char*)secret.c_str(), secret.length());

for (const auto& bptr : in.buffers()) {
hmac.Update((const unsigned char *)bptr.c_str(), bptr.length());
}
sha256_digest_t ret;
hmac.Final(ret.v);

return ret;
}

// ---------------------------------------------------

class CryptoNoneKeyHandler : public CryptoKeyHandler {
Expand Down
9 changes: 9 additions & 0 deletions src/auth/Crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ class CryptoKeyHandler {
const out_slice_t& out) const;
virtual std::size_t decrypt(const in_slice_t& in,
const out_slice_t& out) const;

sha256_digest_t hmac_sha256(const ceph::bufferlist& in) const;
};

/*
Expand Down Expand Up @@ -117,6 +119,8 @@ class CryptoKey {
const bufferptr& get_secret() { return secret; }
const bufferptr& get_secret() const { return secret; }

bool empty() const { return ckh.get() == nullptr; }

void encode_base64(string& s) const {
bufferlist bl;
encode(bl);
Expand Down Expand Up @@ -169,6 +173,11 @@ class CryptoKey {
return ckh->encrypt(in, out);
}

sha256_digest_t hmac_sha256(CephContext*, const ceph::bufferlist& in) {
ceph_assert(ckh);
return ckh->hmac_sha256(in);
}

static constexpr std::size_t get_max_outbuf_size(std::size_t want_size) {
return want_size + CryptoKeyHandler::MAX_BLOCK_SIZE;
}
Expand Down
2 changes: 1 addition & 1 deletion src/common/ceph_crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ void ceph::crypto::shutdown(bool shared)
pthread_mutex_unlock(&crypto_init_mutex);
}

ceph::crypto::HMAC::~HMAC()
ceph::crypto::nss::HMAC::~HMAC()
{
PK11_DestroyContext(ctx, PR_TRUE);
PK11_FreeSymKey(symkey);
Expand Down
131 changes: 110 additions & 21 deletions src/common/ceph_crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
#endif /*USE_NSS*/

#ifdef USE_OPENSSL
#include <openssl/evp.h>
#include <openssl/ossl_typ.h>
#include <openssl/hmac.h>

extern "C" {
const EVP_MD *EVP_md5(void);
Expand Down Expand Up @@ -135,30 +137,10 @@ namespace ceph {
}
#endif /*USE_OPENSSL*/

#if defined(USE_OPENSSL)
namespace ceph {
namespace crypto {
using ceph::crypto::ssl::SHA256;
using ceph::crypto::ssl::MD5;
using ceph::crypto::ssl::SHA1;
}
}
#elif defined(USE_NSS)
namespace ceph {
namespace crypto {
using ceph::crypto::nss::SHA256;
using ceph::crypto::nss::MD5;
using ceph::crypto::nss::SHA1;
}
}
#else
# error "No supported crypto implementation found."
#endif


#ifdef USE_NSS
namespace ceph {
namespace crypto {
namespace crypto::nss {
class HMAC {
private:
PK11SlotInfo *slot;
Expand Down Expand Up @@ -217,7 +199,114 @@ namespace ceph {
};
}
}
#endif

#ifdef USE_OPENSSL
namespace ceph::crypto::ssl {
# if OPENSSL_VERSION_NUMBER < 0x10100000L
class HMAC {
private:
HMAC_CTX mContext;
const EVP_MD *mpType;

public:
HMAC (const EVP_MD *type, const unsigned char *key, size_t length)
: mpType(type) {
::memset(&mContext, 0, sizeof(mContext));
const auto r = HMAC_Init_ex(&mContext, key, length, mpType, nullptr);
ceph_assert_always(r == 1);
}
~HMAC () {
HMAC_CTX_cleanup(&mContext);
}

void Restart () {
const auto r = HMAC_Init_ex(&mContext, nullptr, 0, mpType, nullptr);
ceph_assert_always(r == 1);
}
void Update (const unsigned char *input, size_t length) {
if (length) {
const auto r = HMAC_Update(&mContext, input, length);
ceph_assert_always(r == 1);
}
}
void Final (unsigned char *digest) {
unsigned int s;
const auto r = HMAC_Final(&mContext, digest, &s);
ceph_assert_always(r == 1);
}
};
# else
class HMAC {
private:
HMAC_CTX *mpContext;

public:
HMAC (const EVP_MD *type, const unsigned char *key, size_t length)
: mpContext(HMAC_CTX_new()) {
const auto r = HMAC_Init_ex(mpContext, key, length, type, nullptr);
ceph_assert_always(r == 1);
}
~HMAC () {
HMAC_CTX_free(mpContext);
}

void Restart () {
const EVP_MD * const type = HMAC_CTX_get_md(mpContext);
const auto r = HMAC_Init_ex(mpContext, nullptr, 0, type, nullptr);
ceph_assert_always(r == 1);
}
void Update (const unsigned char *input, size_t length) {
if (length) {
const auto r = HMAC_Update(mpContext, input, length);
ceph_assert_always(r == 1);
}
}
void Final (unsigned char *digest) {
unsigned int s;
const auto r = HMAC_Final(mpContext, digest, &s);
ceph_assert_always(r == 1);
}
};
# endif // OPENSSL_VERSION_NUMBER < 0x10100000L

struct HMACSHA1 : public HMAC {
HMACSHA1 (const unsigned char *key, size_t length)
: HMAC(EVP_sha1(), key, length) {
}
};

struct HMACSHA256 : public HMAC {
HMACSHA256 (const unsigned char *key, size_t length)
: HMAC(EVP_sha256(), key, length) {
}
};
}
#endif /*USE_OPENSSL*/


#if defined(USE_OPENSSL)
namespace ceph {
namespace crypto {
using ceph::crypto::ssl::SHA256;
using ceph::crypto::ssl::MD5;
using ceph::crypto::ssl::SHA1;

using ceph::crypto::ssl::HMACSHA256;
using ceph::crypto::ssl::HMACSHA1;
}
}
#elif defined(USE_NSS)
namespace ceph {
namespace crypto {
using ceph::crypto::nss::SHA256;
using ceph::crypto::nss::MD5;
using ceph::crypto::nss::SHA1;

using ceph::crypto::nss::HMACSHA256;
using ceph::crypto::nss::HMACSHA1;
}
}
#else
// cppcheck-suppress preprocessorErrorDirective
# error "No supported crypto implementation found."
Expand Down
29 changes: 28 additions & 1 deletion src/include/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,8 @@ WRITE_CMP_OPERATORS_1(errorcode32_t, code)
template <uint8_t S>
struct sha_digest_t {
constexpr static uint32_t SIZE = S;
// TODO: we might consider std::array in the future. Avoiding it for now
// as sha_digest_t is a part of our public API.
unsigned char v[S] = {0};

string to_str() const {
Expand All @@ -571,8 +573,29 @@ struct sha_digest_t {
}
return string(str);
}
sha_digest_t(const unsigned char *_v) { memcpy(v, _v, S); };
sha_digest_t(const unsigned char *_v) { memcpy(v, _v, SIZE); };
sha_digest_t() {}

bool operator==(const sha_digest_t& r) const {
return ::memcmp(v, r.v, SIZE) == 0;
}
bool operator!=(const sha_digest_t& r) const {
return ::memcmp(v, r.v, SIZE) != 0;
}

void encode(bufferlist &bl) const {
// copy to avoid reinterpret_cast, is_pod and other nasty things
using ceph::encode;
std::array<unsigned char, SIZE> tmparr;
memcpy(tmparr.data(), v, SIZE);
encode(tmparr, bl);
}
void decode(bufferlist::const_iterator &bl) {
using ceph::decode;
std::array<unsigned char, SIZE> tmparr;
decode(tmparr, bl);
memcpy(v, tmparr.data(), SIZE);
}
};

template <uint8_t S>
Expand All @@ -582,6 +605,10 @@ inline ostream &operator<<(ostream &out, const sha_digest_t<S> &b) {
}

using sha1_digest_t = sha_digest_t<20>;
WRITE_CLASS_ENCODER(sha1_digest_t)

using sha256_digest_t = sha_digest_t<32>;
WRITE_CLASS_ENCODER(sha256_digest_t)


#endif
51 changes: 39 additions & 12 deletions src/msg/async/Protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ class Ct {
template <class C, typename... Args>
class CtFun : public Ct<C> {
private:
using fn = Ct<C> *(C::*)(Args...);
fn _f;
using fn_t = Ct<C> *(C::*)(Args...);
fn_t _f;
std::tuple<Args...> _params;

template <std::size_t... Is>
Expand All @@ -38,34 +38,61 @@ class CtFun : public Ct<C> {
}

public:
CtFun(fn f) : _f(f) {}
CtFun(fn_t f) : _f(f) {}

inline void setParams(Args... args) { _params = std::make_tuple(args...); }
inline Ct<C> *call(C *foo) const override {
return _call(foo, std::index_sequence_for<Args...>());
}
};

#define CONTINUATION_DECL(C, F, ...) \
std::unique_ptr<CtFun<C, ##__VA_ARGS__>> F##_cont_ = \
std::make_unique<CtFun<C, ##__VA_ARGS__>>(&C::F); \
CtFun<C, ##__VA_ARGS__> *F##_cont = F##_cont_.get()
using rx_buffer_t =
std::unique_ptr<buffer::ptr_node, buffer::ptr_node::disposer>;

template <class C>
class CtRxNode : public Ct<C> {
using fn_t = Ct<C> *(C::*)(rx_buffer_t&&, int r);
fn_t _f;

public:
mutable rx_buffer_t node;
int r;

CtRxNode(fn_t f) : _f(f) {}
void setParams(rx_buffer_t &&node, int r) {
this->node = std::move(node);
this->r = r;
}
inline Ct<C> *call(C *foo) const override {
return (foo->*_f)(std::move(node), r);
}
};

#define CONTINUATION_PARAM(V, C, ...) CtFun<C, ##__VA_ARGS__> *V##_cont
template <class C> using CONTINUATION_TYPE = CtFun<C>;
template <class C> using CONTINUATION_TX_TYPE = CtFun<C, int>;
template <class C> using CONTINUATION_RX_TYPE = CtFun<C, char*, int>;
template <class C> using CONTINUATION_RXBPTR_TYPE = CtRxNode<C>;

#define CONTINUATION_DECL(C, F, ...) \
CtFun<C, ##__VA_ARGS__> F##_cont { (&C::F) };

#define CONTINUATION(F) F##_cont
#define CONTINUE(F, ...) F##_cont->setParams(__VA_ARGS__), F##_cont
#define CONTINUE(F, ...) (F##_cont.setParams(__VA_ARGS__), &F##_cont)

#define CONTINUATION_RUN(CT) \
{ \
Ct<std::remove_reference<decltype(*this)>::type> *_cont = CT; \
while (_cont) { \
Ct<std::remove_reference<decltype(*this)>::type> *_cont = &CT;\
do { \
_cont = _cont->call(this); \
} \
} while (_cont); \
}

#define READ_HANDLER_CONTINUATION_DECL(C, F) \
CONTINUATION_DECL(C, F, char *, int)

#define READ_BPTR_HANDLER_CONTINUATION_DECL(C, F) \
CtRxNode<C> F##_cont { (&C::F) };

#define WRITE_HANDLER_CONTINUATION_DECL(C, F) CONTINUATION_DECL(C, F, int)

//////////////////////////////////////////////////////////////////////
Expand Down
Loading

0 comments on commit d216aed

Please sign in to comment.