]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
auth, msg/async, v2: drop AuthStreamHandler and AES128GCM_StreamHandler.
authorRadoslaw Zarzynski <rzarzyns@redhat.com>
Sun, 10 Feb 2019 23:31:49 +0000 (00:31 +0100)
committerRadoslaw Zarzynski <rzarzyns@redhat.com>
Thu, 21 Feb 2019 20:58:19 +0000 (21:58 +0100)
Signed-off-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
src/auth/AuthSessionHandler.cc
src/auth/AuthSessionHandler.h
src/msg/async/ProtocolV2.cc
src/msg/async/ProtocolV2.h

index 54fff27407204461e9f13586dccea3811ade4f38..5835396075b40f2589de99e950ce7c59e525929c 100644 (file)
@@ -55,235 +55,3 @@ AuthSessionHandler *get_auth_session_handler(
   }
 }
 
-
-#ifdef USE_OPENSSL
-# include <openssl/evp.h>
-#endif
-
-// http://www.mindspring.com/~dmcgrew/gcm-nist-6.pdf
-// https://www.openssl.org/docs/man1.0.2/crypto/EVP_aes_128_gcm.html#GCM-mode
-// https://wiki.openssl.org/index.php/EVP_Authenticated_Encryption_and_Decryption
-class AES128GCM_StreamHandler : public AuthStreamHandler {
-  CephContext* const cct;
-  std::unique_ptr<EVP_CIPHER_CTX, decltype(&::EVP_CIPHER_CTX_free)> ectx;
-
-  static constexpr const std::size_t AES_KEY_LEN{16};
-  static constexpr const std::size_t STREAM_AES_IV_LEN{16};
-  static constexpr const std::size_t STREAM_GCM_TAG_LEN{16};
-  static constexpr const std::size_t AES_BLOCK_LEN{16};
-
-  std::array<char, AES_KEY_LEN> connection_secret;
-
-  // using GCC's "Tetra Integer" mode here
-  ceph::uint128_t nonce;
-  static_assert(sizeof(nonce) == STREAM_AES_IV_LEN);
-
-public:
-  AES128GCM_StreamHandler(CephContext* const cct,
-                         const AuthConnectionMeta& auth_meta,
-                         const ceph::uint128_t& nonce)
-    : cct(cct),
-      ectx(EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free),
-      nonce(nonce) {
-    ceph_assert_always(auth_meta.connection_secret.length() >= AES_KEY_LEN);
-    ceph_assert_always(ectx);
-
-    std::copy_n(std::cbegin(auth_meta.connection_secret), AES_KEY_LEN,
-               std::begin(connection_secret));
-    //EVP_CIPHER_CTX_reset(ectx.get());
-  }
-
-  ~AES128GCM_StreamHandler() override {
-    memset(&nonce, 0, sizeof(nonce));
-    //connection_secret.zero();
-  }
-
-  std::size_t calculate_padded_size(const std::size_t length) {
-    // we need to take into account the PKCS#7 padding. There *always* will
-    // be at least one byte of padding. This stays even to input aligned to
-    // AES_BLOCK_LEN. Otherwise we would face ambiguities during decryption.
-    // To exemplify:
-    //   length := 10 -> p2align(10, 16) + 16 == 16 (06 bytes for padding),
-    //   length := 16 -> p2align(16, 16) + 16 == 32 (16 bytes for padding).
-    //
-    // Technically padding will be added by OpenSSL but its format and even
-    // presence is a part of the public interface, I believe.
-    return p2align(length, AES_BLOCK_LEN) + AES_BLOCK_LEN;
-  }
-
-  std::size_t calculate_payload_size(const std::size_t length) override {
-    // as we're doing *authenticated encryption* additional space is needed
-    // to store Auth Tag. OpenSSL defaults this to 96 bits (12 bytes).
-    const std::size_t authenticated_and_encrypted_size = \
-      calculate_padded_size(length) + STREAM_GCM_TAG_LEN;
-    return authenticated_and_encrypted_size;
-  }
-
-  void authenticated_encrypt(ceph::bufferlist& payload) override;
-  void authenticated_decrypt(char* payload, uint32_t& length) override;
-};
-
-void AES128GCM_StreamHandler::authenticated_encrypt(ceph::bufferlist& payload)
-{
-  if (1 != EVP_EncryptInit_ex(ectx.get(), EVP_aes_128_gcm(),
-                             nullptr, nullptr, nullptr)) {
-    throw std::runtime_error("EVP_EncryptInit_ex failed");
-  }
-
-  if (1 != EVP_CIPHER_CTX_ctrl(ectx.get(), EVP_CTRL_GCM_SET_IVLEN,
-                              STREAM_AES_IV_LEN, nullptr) ) {
-    throw std::runtime_error("EVP_CIPHER_CTX_ctrl failed");
-  }
-
-  if(1 != EVP_EncryptInit_ex(ectx.get(), nullptr, nullptr,
-       reinterpret_cast<const unsigned char*>(connection_secret.data()),
-       reinterpret_cast<const unsigned char*>(&nonce))) {
-    throw std::runtime_error("EVP_EncryptInit_ex failed");
-  }
-
-  // TODO: consider in-place transformata
-  auto out_tmp = \
-    ceph::buffer::ptr_node::create(calculate_payload_size(payload.length()));
-
-  // append necessary padding accordingly to PKCS#7
-  {
-    const auto padding_size = \
-      calculate_padded_size(payload.length()) - payload.length();
-    auto filler = payload.append_hole(padding_size);
-    ::memset(filler.c_str(), static_cast<char>(padding_size), padding_size);
-  }
-
-  int update_len = 0;
-  if(1 != EVP_EncryptUpdate(ectx.get(),
-       reinterpret_cast<unsigned char*>(out_tmp->c_str()),
-       &update_len,
-       reinterpret_cast<const unsigned char*>(payload.c_str()),
-       payload.length())) {
-    throw std::runtime_error("EVP_EncryptUpdate failed");
-  }
-
-  int final_len = 0;
-  if(1 != EVP_EncryptFinal_ex(ectx.get(),
-       reinterpret_cast<unsigned char*>(out_tmp->c_str() + update_len),
-       &final_len)) {
-    throw std::runtime_error("EVP_EncryptFinal_ex failed");
-  }
-
-  if(1 != EVP_CIPHER_CTX_ctrl(ectx.get(),
-       EVP_CTRL_GCM_GET_TAG, STREAM_GCM_TAG_LEN,
-       out_tmp->c_str() + update_len + final_len)) {
-    throw std::runtime_error("EVP_CIPHER_CTX_ctrl failed");
-  }
-
-#if 0
-  if (1 != EVP_CIPHER_CTX_cleanup(ectx.get())) {
-    throw std::runtime_error("EVP_CIPHER_CTX_cleanup failed");
-  }
-#endif
-
-  ldout(cct, 15) << __func__
-                << " payload.length()=" << payload.length()
-                << " out_tmp->length()=" << out_tmp->length()
-                << " update_len=" << update_len
-                << " final_len=" << final_len
-                << dendl;
-  ceph_assert(update_len + final_len + STREAM_GCM_TAG_LEN == out_tmp->length());
-
-  payload.clear();
-  payload.push_back(std::move(out_tmp));
-  nonce++;
-}
-
-void AES128GCM_StreamHandler::authenticated_decrypt(
-  char* payload,
-  uint32_t& length)
-{
-  ceph_assert(length > 0);
-  ceph_assert(length % AES_BLOCK_LEN == 0);
-  if (1 != EVP_DecryptInit_ex(ectx.get(), EVP_aes_128_gcm(),
-                             nullptr, nullptr, nullptr)) {
-    throw std::runtime_error("EVP_DecryptInit_ex failed");
-  }
-
-  if (1 != EVP_CIPHER_CTX_ctrl(ectx.get(), EVP_CTRL_GCM_SET_IVLEN,
-                              STREAM_AES_IV_LEN, nullptr) ) {
-    throw std::runtime_error("EVP_CIPHER_CTX_ctrl failed");
-  }
-
-  if(1 != EVP_DecryptInit_ex(ectx.get(), nullptr, nullptr,
-       reinterpret_cast<const unsigned char*>(connection_secret.data()),
-       reinterpret_cast<const unsigned char*>(&nonce))) {
-    throw std::runtime_error("EVP_DecryptInit_ex failed");
-  }
-
-  // TODO: consider in-place transformata
-  auto out_tmp = \
-    ceph::buffer::ptr_node::create(length - STREAM_GCM_TAG_LEN);
-
-  int update_len = 0;
-  if (1 != EVP_DecryptUpdate(ectx.get(),
-       reinterpret_cast<unsigned char*>(out_tmp->c_str()),
-       &update_len,
-       reinterpret_cast<const unsigned char*>(payload),
-       length - STREAM_GCM_TAG_LEN)) {
-    throw std::runtime_error("EVP_DecryptUpdate failed");
-  }
-
-  if (1 != EVP_CIPHER_CTX_ctrl(ectx.get(), EVP_CTRL_GCM_SET_TAG,
-       STREAM_GCM_TAG_LEN,
-       payload + length - STREAM_GCM_TAG_LEN)) {
-    throw std::runtime_error("EVP_CIPHER_CTX_ctrl failed");
-  }
-
-  int final_len = 0;
-  if (0 >= EVP_DecryptFinal_ex(ectx.get(),
-       reinterpret_cast<unsigned char*>(out_tmp->c_str() + update_len),
-       &final_len)) {
-  ldout(cct, 15) << __func__
-                << " length=" << length
-                << " out_tmp->length()=" << out_tmp->length()
-                << " update_len=" << update_len
-                << " final_len=" << final_len
-                << dendl;
-    throw std::runtime_error("EVP_DecryptFinal_ex failed");
-  } else {
-    ceph_assert_always(update_len + final_len + STREAM_GCM_TAG_LEN == length);
-    ceph_assert_always((update_len + final_len) % AES_BLOCK_LEN == 0);
-
-    // BE CAREFUL: we cannot expose any single bit of information about
-    // the cause of failure. Otherwise we'll face padding oracle attack.
-    // See: https://en.wikipedia.org/wiki/Padding_oracle_attack.
-    const auto pad_len = \
-      std::min<std::uint8_t>((*out_tmp)[update_len + final_len - 1], AES_BLOCK_LEN);
-
-    // TODO: move to a new interface after dropping AES-CBC-HMAC-SHA256
-    length = update_len + final_len - pad_len;
-    memcpy(payload, out_tmp->c_str(), length);
-    nonce++;
-  }
-}
-
-
-AuthStreamHandler::rxtx_t AuthStreamHandler::create_stream_handler_pair(
-  CephContext* cct,
-  const class AuthConnectionMeta& auth_meta)
-{
-  if (auth_meta.is_mode_secure()) {
-    // CLEANME, CLEANME CLEANME
-    ceph_assert_always(
-      auth_meta.connection_secret.length() >= 16 + 2*sizeof(ceph::uint128_t));
-
-    ceph::uint128_t rx_nonce;
-    ::memcpy(&rx_nonce, auth_meta.connection_secret.c_str() + 16, sizeof(rx_nonce));
-
-    ceph::uint128_t tx_nonce;
-    ::memcpy(&tx_nonce, auth_meta.connection_secret.c_str() + 16 + sizeof(rx_nonce),
-      sizeof(tx_nonce));
-    return {
-      std::make_unique<AES128GCM_StreamHandler>(cct, auth_meta, rx_nonce),
-      std::make_unique<AES128GCM_StreamHandler>(cct, auth_meta, tx_nonce)
-    };
-  } else {
-    return { nullptr, nullptr };
-  }
-}
index 2b0d952c411b179b13bf9c6aa4a92ee46a065fae..6e54f1cee00dfe5ece84863646babc79f99967db 100644 (file)
@@ -41,45 +41,8 @@ struct DummyAuthSessionHandler : AuthSessionHandler {
   }
 };
 
-struct SHA256SignatureError : public std::exception {
-  sha256_digest_t sig1;
-  sha256_digest_t sig2;
-  std::string reason;
-
-  SHA256SignatureError(const char *sig1, const char *sig2)
-      : sig1((const unsigned char *)sig1), sig2((const unsigned char *)sig2) {
-    std::stringstream ss;
-    ss << " signature mismatch: calc signature=" << this->sig1
-       << " msg signature=" << this->sig2;
-    reason = ss.str();
-  }
-
-  const char *what() const throw() { return reason.c_str(); }
-};
-
 struct DecryptionError : public std::exception {};
 
-struct AuthStreamHandler {
-  virtual ~AuthStreamHandler() = default;
-  //virtual ceph::bufferlist authenticated_encrypt(ceph::bufferlist& in) = 0;
-  //virtual ceph::bufferlist authenticated_decrypt(ceph::bufferlist& in) = 0;
-  virtual void authenticated_encrypt(ceph::bufferlist& payload) = 0;
-  virtual void authenticated_decrypt(char* payload, uint32_t& length) = 0;
-  virtual std::size_t calculate_payload_size(std::size_t length) = 0;
-
-  struct rxtx_t {
-    //rxtx_t(rxtx_t&& r) : rx(std::move(rx)), tx(std::move(tx)) {}
-    // Each peer can use different handlers.
-    // Hmm, isn't that too much flexbility?
-    std::unique_ptr<AuthStreamHandler> rx;
-    std::unique_ptr<AuthStreamHandler> tx;
-  };
-  static rxtx_t create_stream_handler_pair(
-    CephContext* ctx,
-    const class AuthConnectionMeta& auth_meta);
-};
-
-// TODO: make this a static member of AuthSessionHandler.
 extern AuthSessionHandler *get_auth_session_handler(
   CephContext *cct, int protocol,
   const CryptoKey& key,
index 3dac54b350c1d9dc6017ad721fd78ee7f562db2a..5a856d71c9793f77ba910e385551c565b9c6b365 100644 (file)
@@ -277,13 +277,6 @@ template <class T, typename... Args>
 struct SignedEncryptedFrame : public PayloadFrame<T, Args...> {
   SignedEncryptedFrame(ProtocolV2 &protocol, const Args &... args)
       : PayloadFrame<T, Args...>(args...) {
-#if 0
-    ceph::bufferlist trans_bl;
-    this->payload.splice(8, this->payload.length() - 8, &trans_bl);
-    protocol.authencrypt_payload(trans_bl);
-    this->payload.claim_append(trans_bl);
-
-#else
     ceph_assert(protocol.session_stream_handlers.tx);
 
     protocol.session_stream_handlers.tx->reset_tx_handler({
@@ -301,15 +294,10 @@ struct SignedEncryptedFrame : public PayloadFrame<T, Args...> {
       std::move(this->payload));
     this->payload = \
       protocol.session_stream_handlers.tx->authenticated_encrypt_final();
-#endif
   }
 
   SignedEncryptedFrame(ProtocolV2 &protocol, char *payload, uint32_t length)
       : PayloadFrame<T, Args...>() {
-#if 0
-    protocol.authdecrypt_payload(payload, length);
-    this->decode_frame(payload, length);
-#else
     protocol.session_stream_handlers.rx->reset_rx_handler();
 
     ceph::bufferlist bl;
@@ -319,7 +307,6 @@ struct SignedEncryptedFrame : public PayloadFrame<T, Args...> {
       protocol.session_stream_handlers.rx->authenticated_decrypt_update_final(
         std::move(bl), 8);
     this->decode_frame(plain_bl.c_str(), plain_bl.length());
-#endif
   }
 };
 
@@ -1121,40 +1108,6 @@ bool ProtocolV2::is_queued() {
   return !out_queue.empty() || connection->is_queued();
 }
 
-uint32_t ProtocolV2::calculate_payload_size(
-  AuthStreamHandler *stream_handler,
-  uint32_t length)
-{
-#if 0
-  if (auth_meta.is_mode_secure()) {
-    ceph_assert(stream_handler != nullptr);
-    return stream_handler->calculate_payload_size(length);
-  } else {
-    return length;
-  }
-#else
-  return length;
-#endif
-}
-
-void ProtocolV2::authencrypt_payload(bufferlist &payload) {
-  if (auth_meta->is_mode_secure()) {
-    // using tx
-    ceph_assert(session_security.tx);
-    session_security.tx->authenticated_encrypt(payload);
-    ceph_assert(payload.length() > 0);
-  }
-}
-
-void ProtocolV2::authdecrypt_payload(char *payload, uint32_t &length) {
-  if (auth_meta->is_mode_secure()) {
-    ceph_assert(session_security.rx);
-    // using rx
-    ceph_assert(length > 0);
-    session_security.rx->authenticated_decrypt(payload, length);
-  }
-}
-
 CtPtr ProtocolV2::read(CONTINUATION_PARAM(next, ProtocolV2, char *, int),
                        int len, char *buffer) {
   if (!buffer) {
@@ -2910,7 +2863,6 @@ CtPtr ProtocolV2::reuse_connection(AsyncConnectionRef existing,
   exproto->can_write = false;
   exproto->reconnecting = reconnecting;
   exproto->replacing = true;
-  std::swap(exproto->session_security, session_security);
   std::swap(exproto->session_stream_handlers, session_stream_handlers);
   exproto->auth_meta = auth_meta;
   existing->state_offset = 0;
index 92f64fa7b60e25a2f013b9a5a13ed7a29ef64fd4..8589015d6124842b435a48da0d2f4efd63fd3ed9 100644 (file)
@@ -78,7 +78,6 @@ private:
   char *temp_buffer;
   State state;
   uint64_t peer_required_features;
-  AuthStreamHandler::rxtx_t session_security;
 
   uint64_t client_cookie;
   uint64_t server_cookie;
@@ -204,13 +203,6 @@ public:
   virtual void write_event() override;
   virtual bool is_queued() override;
 
-  uint32_t calculate_payload_size(
-    AuthStreamHandler *stream_handler,
-    uint32_t length);
-  // We are doing *authenticated encryption*
-  void authencrypt_payload(ceph::bufferlist &payload);
-  void authdecrypt_payload(char *payload, uint32_t &length);
-
 private:
   // Client Protocol
   CONTINUATION_DECL(ProtocolV2, start_client_banner_exchange);