Skip to content

Commit

Permalink
msg/async, v2: drop depedency on uint128_t. Clean up onwire crypto.
Browse files Browse the repository at this point in the history
Signed-off-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
  • Loading branch information
rzarzynski committed Feb 21, 2019
1 parent fa7e6d6 commit fe387e0
Showing 1 changed file with 54 additions and 43 deletions.
97 changes: 54 additions & 43 deletions src/msg/async/crypto_onwire.cc
@@ -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"
Expand All @@ -10,43 +11,49 @@

#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)) {
throw std::runtime_error("EVP_EncryptInit_ex failed");
}

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");
}
}
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -133,40 +139,31 @@ 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)) {
throw std::runtime_error("EVP_DecryptInit_ex failed");
}

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");
}
}
Expand All @@ -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(
Expand Down Expand Up @@ -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

0 comments on commit fe387e0

Please sign in to comment.