]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
msg/async, v2: drop depedency on uint128_t. Clean up onwire crypto.
authorRadoslaw Zarzynski <rzarzyns@redhat.com>
Wed, 20 Feb 2019 15:01:28 +0000 (16:01 +0100)
committerRadoslaw Zarzynski <rzarzyns@redhat.com>
Thu, 21 Feb 2019 22:31:03 +0000 (23:31 +0100)
Signed-off-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
src/msg/async/crypto_onwire.cc

index e04b63800ca04326f9205ae9374142b24e676bce..0cd272eae4cd3043631fc2c076f117f5dc2d97e0 100644 (file)
@@ -1,6 +1,7 @@
 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
 // vim: ts=8 sw=2 smarttab
 
+#include <array>
 #include <openssl/evp.h>
 
 #include "crypto_onwire.h"
 
 #define dout_subsys ceph_subsys_ms
 
+namespace ceph::crypto::onwire {
+
+static constexpr const std::size_t AESGCM_KEY_LEN{16};
+static constexpr const std::size_t AESGCM_IV_LEN{12};
+static constexpr const std::size_t AESGCM_TAG_LEN{16};
+static constexpr const std::size_t AESGCM_BLOCK_LEN{16};
+
+struct nonce_t {
+  std::uint32_t random_seq;
+  std::uint64_t random_rest;
+} __attribute__((packed));
+static_assert(sizeof(nonce_t) == AESGCM_IV_LEN);
+
+using key_t = std::array<std::uint8_t, AESGCM_KEY_LEN>;
+
 // 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
 // https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf
 class AES128GCM_OnWireTxHandler : public ceph::crypto::onwire::TxHandler {
-  static constexpr const std::size_t AESGCM_KEY_LEN{16};
-  static constexpr const std::size_t AESGCM_IV_LEN{12};
-  static constexpr const std::size_t AESGCM_TAG_LEN{16};
-  static constexpr const std::size_t AESGCM_BLOCK_LEN{16};
-
-  using nonce_t = std::array<unsigned char, AESGCM_IV_LEN>;
-
   CephContext* const cct;
   std::unique_ptr<EVP_CIPHER_CTX, decltype(&::EVP_CIPHER_CTX_free)> ectx;
   ceph::bufferlist buffer;
-  // using GCC's "Tetra Integer" mode here
-  ceph::uint128_t nonce;
+  nonce_t nonce;
+  static_assert(sizeof(nonce) == AESGCM_IV_LEN);
 
 public:
   AES128GCM_OnWireTxHandler(CephContext* const cct,
-                           const AuthConnectionMeta& auth_meta,
-                           const ceph::uint128_t& nonce)
+                           const key_t& key,
+                           const nonce_t& nonce)
     : cct(cct),
       ectx(EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free),
       nonce(nonce) {
-    ceph_assert_always(auth_meta.connection_secret.length() >= AESGCM_KEY_LEN);
     ceph_assert_always(ectx);
+    ceph_assert_always(key.size() * CHAR_BIT == 128);
 
     if (1 != EVP_EncryptInit_ex(ectx.get(), EVP_aes_128_gcm(),
                                nullptr, nullptr, nullptr)) {
@@ -44,9 +53,7 @@ public:
     }
 
     if(1 != EVP_EncryptInit_ex(ectx.get(), nullptr, nullptr,
-       reinterpret_cast<const unsigned char*>(auth_meta.connection_secret.c_str()),
-       nullptr)) {
-       //reinterpret_cast<const unsigned char*>(&nonce))) {
+                              key.data(), nullptr)) {
       throw std::runtime_error("EVP_EncryptInit_ex failed");
     }
   }
@@ -78,8 +85,7 @@ void AES128GCM_OnWireTxHandler::reset_tx_handler(
   buffer.reserve(std::accumulate(std::begin(update_size_sequence),
     std::end(update_size_sequence), AESGCM_TAG_LEN));
 
-  // transplantate the nonce update management from OpenVPN's AES-GCM
-  nonce += 1ULL << 32;
+  ++nonce.random_seq;
 }
 
 void AES128GCM_OnWireTxHandler::authenticated_encrypt_update(
@@ -133,31 +139,23 @@ ceph::bufferlist AES128GCM_OnWireTxHandler::authenticated_encrypt_final()
   return std::move(buffer);
 }
 
-
 // RX PART
 class AES128GCM_OnWireRxHandler : public ceph::crypto::onwire::RxHandler {
-  static constexpr const std::size_t AESGCM_KEY_LEN{16};
-  static constexpr const std::size_t AESGCM_IV_LEN{12};
-  static constexpr const std::size_t AESGCM_TAG_LEN{16};
-  static constexpr const std::size_t AESGCM_BLOCK_LEN{16};
-
-  using nonce_t = std::array<unsigned char, AESGCM_IV_LEN>;
-
   CephContext* const cct;
   std::unique_ptr<EVP_CIPHER_CTX, decltype(&::EVP_CIPHER_CTX_free)> ectx;
-  // using GCC's "Tetra Integer" mode here
-  ceph::uint128_t nonce;
+  nonce_t nonce;
+  static_assert(sizeof(nonce) == AESGCM_IV_LEN);
 
 public:
   AES128GCM_OnWireRxHandler(CephContext* const cct,
-                           const AuthConnectionMeta& auth_meta,
-                           const ceph::uint128_t& nonce)
+                           const key_t& key,
+                           const nonce_t& nonce)
     : cct(cct),
       ectx(EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free),
       nonce(nonce)
   {
-    ceph_assert_always(auth_meta.connection_secret.length() >= AESGCM_KEY_LEN);
     ceph_assert_always(ectx);
+    ceph_assert_always(key.size() * CHAR_BIT == 128);
 
     if (1 != EVP_DecryptInit_ex(ectx.get(), EVP_aes_128_gcm(),
                                nullptr, nullptr, nullptr)) {
@@ -165,8 +163,7 @@ public:
     }
 
     if(1 != EVP_DecryptInit_ex(ectx.get(), nullptr, nullptr,
-         reinterpret_cast<const unsigned char*>(auth_meta.connection_secret.c_str()),
-         nullptr)) {
+                              key.data(), nullptr)) {
       throw std::runtime_error("EVP_DecryptInit_ex failed");
     }
   }
@@ -193,7 +190,7 @@ void AES128GCM_OnWireRxHandler::reset_rx_handler()
        reinterpret_cast<const unsigned char*>(&nonce))) {
     throw std::runtime_error("EVP_DecryptInit_ex failed");
   }
-  nonce += 1ULL << 32;
+  ++nonce.random_seq;
 }
 
 ceph::bufferlist AES128GCM_OnWireRxHandler::authenticated_decrypt_update(
@@ -288,23 +285,37 @@ ceph::crypto::onwire::rxtx_t ceph::crypto::onwire::rxtx_t::create_handler_pair(
   bool crossed)
 {
   if (auth_meta.is_mode_secure()) {
-    // CLEANME, CLEANME CLEANME
-    ceph_assert_always(
-      auth_meta.connection_secret.length() >= 16 + 2*sizeof(ceph::uint128_t));
+    ceph_assert_always(auth_meta.connection_secret.length() >= \
+      sizeof(key_t) + 2 * sizeof(nonce_t));
+    const char* secbuf = auth_meta.connection_secret.c_str();
+
+    key_t key;
+    {
+      ::memcpy(key.data(), secbuf, sizeof(key));
+      secbuf += sizeof(key);
+    }
 
-    ceph::uint128_t rx_nonce;
-    ::memcpy(&rx_nonce, auth_meta.connection_secret.c_str() + 16, sizeof(rx_nonce));
+    nonce_t rx_nonce;
+    {
+      ::memcpy(&rx_nonce, secbuf, sizeof(rx_nonce));
+      secbuf += sizeof(rx_nonce);
+    }
+
+    nonce_t tx_nonce;
+    {
+      ::memcpy(&tx_nonce, secbuf, sizeof(tx_nonce));
+      secbuf += sizeof(tx_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_OnWireRxHandler>(
-       cct, auth_meta, crossed ? tx_nonce : rx_nonce),
+       cct, key, crossed ? tx_nonce : rx_nonce),
       std::make_unique<AES128GCM_OnWireTxHandler>(
-       cct, auth_meta, crossed ? rx_nonce : tx_nonce)
+       cct, key, crossed ? rx_nonce : tx_nonce)
     };
   } else {
     return { nullptr, nullptr };
   }
 }
+
+} // namespace ceph::crypto::onwire