return _fault();
}
auth_meta->con_mode = auth_done.con_mode();
- session_stream_handlers = \
- ceph::crypto::onwire::rxtx_t::create_handler_pair(cct, *auth_meta, false);
+ session_stream_handlers = ceph::crypto::onwire::rxtx_t::create_handler_pair(
+ cct, *auth_meta, /*new_nonce_format=*/false, /*crossed=*/false);
state = AUTH_CONNECTING_SIGN;
ceph_assert(auth_meta);
// TODO: having a possibility to check whether we're server or client could
// allow reusing finish_auth().
- session_stream_handlers = \
- ceph::crypto::onwire::rxtx_t::create_handler_pair(cct, *auth_meta, true);
+ session_stream_handlers = ceph::crypto::onwire::rxtx_t::create_handler_pair(
+ cct, *auth_meta, /*new_nonce_format=*/false, /*crossed=*/true);
const auto sig = auth_meta->session_key.empty() ? sha256_digest_t() :
auth_meta->session_key.hmac_sha256(cct, pre_auth.rxbuf);
static constexpr const std::size_t AESGCM_BLOCK_LEN{16};
struct nonce_t {
- ceph_le32 random_seq;
- ceph_le64 random_rest;
+ ceph_le32 fixed;
+ ceph_le64 counter;
bool operator==(const nonce_t& rhs) const {
return !memcmp(this, &rhs, sizeof(*this));
ceph::bufferlist buffer;
nonce_t nonce, initial_nonce;
bool used_initial_nonce;
+ bool new_nonce_format; // 64-bit counter?
static_assert(sizeof(nonce) == AESGCM_IV_LEN);
public:
AES128GCM_OnWireTxHandler(CephContext* const cct,
const key_t& key,
- const nonce_t& nonce)
+ const nonce_t& nonce,
+ bool new_nonce_format)
: cct(cct),
ectx(EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free),
- nonce(nonce), initial_nonce(nonce), used_initial_nonce(false) {
+ nonce(nonce), initial_nonce(nonce), used_initial_nonce(false),
+ new_nonce_format(new_nonce_format) {
ceph_assert_always(ectx);
ceph_assert_always(key.size() * CHAR_BIT == 128);
ceph_assert(buffer.get_append_buffer_unused_tail_length() == 0);
buffer.reserve(std::accumulate(first, last, AESGCM_TAG_LEN));
- nonce.random_seq = nonce.random_seq + 1;
+ if (!new_nonce_format) {
+ // msgr2.0: 32-bit counter followed by 64-bit fixed field,
+ // susceptible to overflow!
+ nonce.fixed = nonce.fixed + 1;
+ } else {
+ nonce.counter = nonce.counter + 1;
+ }
}
void AES128GCM_OnWireTxHandler::authenticated_encrypt_update(
CephContext* const cct;
std::unique_ptr<EVP_CIPHER_CTX, decltype(&::EVP_CIPHER_CTX_free)> ectx;
nonce_t nonce;
+ bool new_nonce_format; // 64-bit counter?
static_assert(sizeof(nonce) == AESGCM_IV_LEN);
public:
AES128GCM_OnWireRxHandler(CephContext* const cct,
const key_t& key,
- const nonce_t& nonce)
+ const nonce_t& nonce,
+ bool new_nonce_format)
: cct(cct),
ectx(EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free),
- nonce(nonce)
- {
+ nonce(nonce), new_nonce_format(new_nonce_format) {
ceph_assert_always(ectx);
ceph_assert_always(key.size() * CHAR_BIT == 128);
reinterpret_cast<const unsigned char*>(&nonce))) {
throw std::runtime_error("EVP_DecryptInit_ex failed");
}
- nonce.random_seq = nonce.random_seq + 1;
+
+ if (!new_nonce_format) {
+ // msgr2.0: 32-bit counter followed by 64-bit fixed field,
+ // susceptible to overflow!
+ nonce.fixed = nonce.fixed + 1;
+ } else {
+ nonce.counter = nonce.counter + 1;
+ }
}
void AES128GCM_OnWireRxHandler::authenticated_decrypt_update(
ceph::crypto::onwire::rxtx_t ceph::crypto::onwire::rxtx_t::create_handler_pair(
CephContext* cct,
const AuthConnectionMeta& auth_meta,
+ bool new_nonce_format,
bool crossed)
{
if (auth_meta.is_mode_secure()) {
return {
std::make_unique<AES128GCM_OnWireRxHandler>(
- cct, key, crossed ? tx_nonce : rx_nonce),
+ cct, key, crossed ? tx_nonce : rx_nonce, new_nonce_format),
std::make_unique<AES128GCM_OnWireTxHandler>(
- cct, key, crossed ? rx_nonce : tx_nonce)
+ cct, key, crossed ? rx_nonce : tx_nonce, new_nonce_format)
};
} else {
return { nullptr, nullptr };