Use pools for GCM contexts

This commit is contained in:
Vitaliy Filippov
2026-07-05 14:58:23 +03:00
parent dbed0e94cb
commit 32e651ec96
6 changed files with 134 additions and 80 deletions
+14 -22
View File
@@ -236,15 +236,23 @@ osd_messenger_t::~osd_messenger_t()
rdmacm_evch = NULL; rdmacm_evch = NULL;
} }
#endif #endif
for (auto encrypt_ctx: encrypt_ctx_pool) for (auto encrypt_ctx: encrypt_xts_pool)
{ {
destroy_aes_xts_encrypt(encrypt_ctx); destroy_aes_xts_encrypt(encrypt_ctx);
} }
for (auto decrypt_ctx: decrypt_ctx_pool) for (auto decrypt_ctx: decrypt_xts_pool)
{ {
destroy_aes_xts_decrypt(decrypt_ctx); destroy_aes_xts_decrypt(decrypt_ctx);
} }
#ifdef WITH_OPENSSL #ifdef WITH_OPENSSL
for (EVP_CIPHER_CTX *ctx: encrypt_gcm_pool)
{
EVP_CIPHER_CTX_free(ctx);
}
for (EVP_CIPHER_CTX *ctx: decrypt_gcm_pool)
{
EVP_CIPHER_CTX_free(ctx);
}
if (ssl_ctx) if (ssl_ctx)
{ {
SSL_CTX_free(ssl_ctx); SSL_CTX_free(ssl_ctx);
@@ -285,9 +293,9 @@ void osd_messenger_t::parse_config(const json11::Json & config)
if (!this->rdma_max_msg || this->rdma_max_msg > 128*1024*1024) if (!this->rdma_max_msg || this->rdma_max_msg > 128*1024*1024)
this->rdma_max_msg = 129*1024; this->rdma_max_msg = 129*1024;
#endif #endif
this->max_aes_xts_pool_size = config["max_aes_xts_pool_size"].uint64_value(); this->max_cipher_pool_size = config["max_cipher_pool_size"].uint64_value();
if (!this->max_aes_xts_pool_size) if (!this->max_cipher_pool_size)
this->max_aes_xts_pool_size = 256; this->max_cipher_pool_size = 256;
if (config["proto_checksums"].is_null()) if (config["proto_checksums"].is_null())
this->use_proto_checksums = MSGR_CSUM_PAYLOAD; this->use_proto_checksums = MSGR_CSUM_PAYLOAD;
else if (config["proto_checksums"].is_bool()) else if (config["proto_checksums"].is_bool())
@@ -825,23 +833,7 @@ void osd_messenger_t::ssl_init(osd_client_t *cl, bool server_mode)
} }
else if (!test_osd_aes_key.empty()) else if (!test_osd_aes_key.empty())
{ {
int r; cl->gcm_enabled = true;
cl->enc_ctx = EVP_CIPHER_CTX_new();
assert(cl->enc_ctx);
r = EVP_EncryptInit_ex(cl->enc_ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
assert(r == 1);
r = EVP_CIPHER_CTX_set_padding(cl->enc_ctx, 0);
assert(r == 1);
r = EVP_CIPHER_CTX_ctrl(cl->enc_ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL);
assert(r == 1);
cl->dec_ctx = EVP_CIPHER_CTX_new();
assert(cl->dec_ctx);
r = EVP_DecryptInit_ex(cl->dec_ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
assert(r == 1);
r = EVP_CIPHER_CTX_set_padding(cl->dec_ctx, 0);
assert(r == 1);
r = EVP_CIPHER_CTX_ctrl(cl->dec_ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL);
assert(r == 1);
} }
} }
+9 -5
View File
@@ -104,6 +104,7 @@ struct osd_client_t
size_t ssl_read_header_size = 0; size_t ssl_read_header_size = 0;
bool ssl_more_to_buffer = false; bool ssl_more_to_buffer = false;
bool gcm_enabled = false;
EVP_CIPHER_CTX *enc_ctx = NULL; EVP_CIPHER_CTX *enc_ctx = NULL;
uint8_t enc_tag[16]; uint8_t enc_tag[16];
size_t enc_tag_size = 0; size_t enc_tag_size = 0;
@@ -125,7 +126,7 @@ struct osd_client_t
uint64_t read_op_id = 1; uint64_t read_op_id = 1;
bool check_sequencing = false; bool check_sequencing = false;
bool enable_pg_locks = false; bool enable_pg_locks = false;
op_aes_xts_decrypt_t *decrypt_ctx = NULL; op_aes_xts_decrypt_t *xts_dec_ctx = NULL;
size_t read_op_inline_decrypt_pos = 0; size_t read_op_inline_decrypt_pos = 0;
size_t read_op_inline_decrypt_in = 0; size_t read_op_inline_decrypt_in = 0;
int proto_csum_status = 0; int proto_csum_status = 0;
@@ -151,7 +152,7 @@ struct osd_client_t
size_t send_list_size = 0; size_t send_list_size = 0;
std::deque<osd_op_t*> send_free_ops; std::deque<osd_op_t*> send_free_ops;
std::vector<osd_op_t*> zc_free_list; std::vector<osd_op_t*> zc_free_list;
op_aes_xts_encrypt_t *encrypt_ctx = NULL; op_aes_xts_encrypt_t *xts_enc_ctx = NULL;
XXH3_state_t* write_csum_state = NULL; XXH3_state_t* write_csum_state = NULL;
~osd_client_t(); ~osd_client_t();
@@ -220,7 +221,7 @@ protected:
bool use_sync_send_recv = false; bool use_sync_send_recv = false;
int min_zerocopy_send_size = DEFAULT_MIN_ZEROCOPY_SEND_SIZE; int min_zerocopy_send_size = DEFAULT_MIN_ZEROCOPY_SEND_SIZE;
int iothread_count = 0; int iothread_count = 0;
int max_aes_xts_pool_size = 256; int max_cipher_pool_size = 256;
std::string tls_cert; std::string tls_cert;
std::string tls_key; std::string tls_key;
@@ -258,8 +259,11 @@ protected:
// We don't use ringloop->set_immediate here because we may have no ringloop in client :) // We don't use ringloop->set_immediate here because we may have no ringloop in client :)
std::deque<osd_op_t*> set_immediate_ops; std::deque<osd_op_t*> set_immediate_ops;
std::vector<op_aes_xts_encrypt_t*> encrypt_ctx_pool; std::vector<op_aes_xts_encrypt_t*> encrypt_xts_pool;
std::vector<op_aes_xts_decrypt_t*> decrypt_ctx_pool; std::vector<op_aes_xts_decrypt_t*> decrypt_xts_pool;
std::vector<EVP_CIPHER_CTX*> encrypt_gcm_pool;
std::vector<EVP_CIPHER_CTX*> decrypt_gcm_pool;
public: public:
timerfd_manager_t *tfd = NULL; timerfd_manager_t *tfd = NULL;
+26 -26
View File
@@ -335,23 +335,23 @@ void destroy_aes_xts_decrypt(op_aes_xts_decrypt_t *decrypt_ctx)
void osd_messenger_t::op_encrypted_copy_buf(osd_client_t *cl, uint8_t *enc_buf, size_t enc_len, uint8_t *plain, size_t plain_len, size_t & done_plain, size_t & done_enc) void osd_messenger_t::op_encrypted_copy_buf(osd_client_t *cl, uint8_t *enc_buf, size_t enc_len, uint8_t *plain, size_t plain_len, size_t & done_plain, size_t & done_enc)
{ {
if (!cl->encrypt_ctx) if (!cl->xts_enc_ctx)
{ {
if (encrypt_ctx_pool.size()) if (encrypt_xts_pool.size())
{ {
cl->encrypt_ctx = encrypt_ctx_pool.back(); cl->xts_enc_ctx = encrypt_xts_pool.back();
encrypt_ctx_pool.pop_back(); encrypt_xts_pool.pop_back();
} }
else else
cl->encrypt_ctx = new op_aes_xts_encrypt_t(); cl->xts_enc_ctx = new op_aes_xts_encrypt_t();
assert(cl->write_op->enc->key_chain[0]); assert(cl->write_op->enc->key_chain[0]);
cl->encrypt_ctx->start(cl->write_op->enc->key_chain[0], cl->write_op->req.rw.offset, cl->write_op->enc->bitmap_granularity); cl->xts_enc_ctx->start(cl->write_op->enc->key_chain[0], cl->write_op->req.rw.offset, cl->write_op->enc->bitmap_granularity);
} }
while (done_enc < enc_len && (done_plain < plain_len || cl->encrypt_ctx->has_buffered())) while (done_enc < enc_len && (done_plain < plain_len || cl->xts_enc_ctx->has_buffered()))
{ {
size_t done_in = 0; size_t done_in = 0;
size_t done_out = 0; size_t done_out = 0;
cl->encrypt_ctx->update(plain+done_plain, plain_len-done_plain, enc_buf+done_enc, enc_len-done_enc, done_in, done_out); cl->xts_enc_ctx->update(plain+done_plain, plain_len-done_plain, enc_buf+done_enc, enc_len-done_enc, done_in, done_out);
if (cl->write_csum_state && done_out > 0) if (cl->write_csum_state && done_out > 0)
XXH3_64bits_update(cl->write_csum_state, enc_buf+done_enc, done_out); XXH3_64bits_update(cl->write_csum_state, enc_buf+done_enc, done_out);
done_enc += done_out; done_enc += done_out;
@@ -368,7 +368,7 @@ void osd_messenger_t::op_decrypted_copy_buf(osd_client_t *cl, uint8_t *enc_buf,
size_t done_in = 0; size_t done_in = 0;
size_t done_out = 0; size_t done_out = 0;
// plain == NULL means skip output // plain == NULL means skip output
cl->decrypt_ctx->update(enc_buf+done_enc, enc_len-done_enc, plain ? plain+done_plain : NULL, plain_len-done_plain, done_in, done_out); cl->xts_dec_ctx->update(enc_buf+done_enc, enc_len-done_enc, plain ? plain+done_plain : NULL, plain_len-done_plain, done_in, done_out);
if (cl->read_csum_state && done_in > 0) if (cl->read_csum_state && done_in > 0)
XXH3_64bits_update(cl->read_csum_state, enc_buf+done_enc, done_in); XXH3_64bits_update(cl->read_csum_state, enc_buf+done_enc, done_in);
done_enc += done_in; done_enc += done_in;
@@ -380,18 +380,18 @@ void osd_messenger_t::op_decrypted_copy_buf(osd_client_t *cl, uint8_t *enc_buf,
void osd_messenger_t::op_decrypt_start(osd_client_t* cl) void osd_messenger_t::op_decrypt_start(osd_client_t* cl)
{ {
if (!cl->decrypt_ctx) if (!cl->xts_dec_ctx)
{ {
if (decrypt_ctx_pool.size()) if (decrypt_xts_pool.size())
{ {
cl->decrypt_ctx = decrypt_ctx_pool.back(); cl->xts_dec_ctx = decrypt_xts_pool.back();
decrypt_ctx_pool.pop_back(); decrypt_xts_pool.pop_back();
} }
else else
cl->decrypt_ctx = new op_aes_xts_decrypt_t(); cl->xts_dec_ctx = new op_aes_xts_decrypt_t();
auto & enc = cl->read_op->enc; auto & enc = cl->read_op->enc;
assert(cl->read_op->req.hdr.opcode == OSD_OP_READ); assert(cl->read_op->req.hdr.opcode == OSD_OP_READ);
cl->decrypt_ctx->start(enc->key_chain, enc->chain_size, cl->xts_dec_ctx->start(enc->key_chain, enc->chain_size,
(cl->read_op->req.rw.flags & OSD_OP_RETURN_CHAIN) ? (uint8_t*)cl->read_op->bitmap + enc->read_chain_bitmap_pos : 0, (cl->read_op->req.rw.flags & OSD_OP_RETURN_CHAIN) ? (uint8_t*)cl->read_op->bitmap + enc->read_chain_bitmap_pos : 0,
cl->read_op->req.rw.offset, enc->bitmap_granularity); cl->read_op->req.rw.offset, enc->bitmap_granularity);
} }
@@ -423,7 +423,7 @@ void osd_messenger_t::op_decrypt_inline(osd_client_t* cl)
size_t out_len = op->iov.buf[j].iov_len - from_out; size_t out_len = op->iov.buf[j].iov_len - from_out;
size_t done_in = 0; size_t done_in = 0;
size_t done_out = 0; size_t done_out = 0;
cl->decrypt_ctx->update(in, in_len, out, out_len, done_in, done_out); cl->xts_dec_ctx->update(in, in_len, out, out_len, done_in, done_out);
if (done_in >= in_len) if (done_in >= in_len)
{ {
i++; i++;
@@ -444,24 +444,24 @@ void osd_messenger_t::op_decrypt_inline(osd_client_t* cl)
void osd_messenger_t::op_decrypt_free(osd_client_t* cl) void osd_messenger_t::op_decrypt_free(osd_client_t* cl)
{ {
if (cl->decrypt_ctx) if (cl->xts_dec_ctx)
{ {
if (decrypt_ctx_pool.size() > max_aes_xts_pool_size) if (decrypt_xts_pool.size() > max_cipher_pool_size)
delete cl->decrypt_ctx; delete cl->xts_dec_ctx;
else else
decrypt_ctx_pool.push_back(cl->decrypt_ctx); decrypt_xts_pool.push_back(cl->xts_dec_ctx);
cl->decrypt_ctx = NULL; cl->xts_dec_ctx = NULL;
} }
} }
void osd_messenger_t::op_encrypt_free(osd_client_t* cl) void osd_messenger_t::op_encrypt_free(osd_client_t* cl)
{ {
if (cl->encrypt_ctx) if (cl->xts_enc_ctx)
{ {
if (encrypt_ctx_pool.size() > max_aes_xts_pool_size) if (encrypt_xts_pool.size() > max_cipher_pool_size)
delete cl->encrypt_ctx; delete cl->xts_enc_ctx;
else else
encrypt_ctx_pool.push_back(cl->encrypt_ctx); encrypt_xts_pool.push_back(cl->xts_enc_ctx);
cl->encrypt_ctx = NULL; cl->xts_enc_ctx = NULL;
} }
} }
+28 -3
View File
@@ -288,6 +288,26 @@ public:
void reset() void reset()
{ {
from = cl->read_op_pos; from = cl->read_op_pos;
if (!cl->dec_ctx)
{
if (msgr->decrypt_gcm_pool.size())
{
cl->dec_ctx = msgr->decrypt_gcm_pool.back();
msgr->decrypt_gcm_pool.pop_back();
}
else
{
cl->dec_ctx = EVP_CIPHER_CTX_new();
assert(cl->dec_ctx);
int r = EVP_DecryptInit_ex(cl->dec_ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
if (r != 1)
{
fprintf(stderr, "DecryptInit error: ");
ERR_print_errors_fp(stderr);
abort();
}
}
}
uint8_t iv[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; uint8_t iv[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
int r = EVP_DecryptInit_ex(cl->dec_ctx, NULL, NULL, (uint8_t*)msgr->test_osd_aes_key.data(), iv); int r = EVP_DecryptInit_ex(cl->dec_ctx, NULL, NULL, (uint8_t*)msgr->test_osd_aes_key.data(), iv);
if (r != 1) if (r != 1)
@@ -401,6 +421,11 @@ public:
cl->io_error = true; cl->io_error = true;
return false; return false;
} }
if (msgr->decrypt_gcm_pool.size() < msgr->max_cipher_pool_size)
msgr->decrypt_gcm_pool.push_back(cl->dec_ctx);
else
EVP_CIPHER_CTX_free(cl->dec_ctx);
cl->dec_ctx = NULL;
cl->dec_tag_size = 0; cl->dec_tag_size = 0;
assert(len == 0); assert(len == 0);
return true; return true;
@@ -462,7 +487,7 @@ public:
bool read(uint8_t *dst, size_t dst_len, int flags) override bool read(uint8_t *dst, size_t dst_len, int flags) override
{ {
if (cl->dec_ctx) if (cl->gcm_enabled)
return false; // FIXME Only for tests, use copy-only with AES return false; // FIXME Only for tests, use copy-only with AES
if (from >= dst_len) if (from >= dst_len)
{ {
@@ -496,7 +521,7 @@ public:
bool finish() override bool finish() override
{ {
if (cl->dec_ctx) if (cl->gcm_enabled)
return false; return false;
return true; return true;
} }
@@ -692,7 +717,7 @@ void osd_messenger_t::handle_immediate_ops()
bool osd_messenger_t::handle_read_buffer(osd_client_t *cl, uint8_t *curbuf, size_t bufsize) bool osd_messenger_t::handle_read_buffer(osd_client_t *cl, uint8_t *curbuf, size_t bufsize)
{ {
if (cl->dec_ctx) if (cl->gcm_enabled)
{ {
return handle_buffer_with<gcm_op_reader_t>(cl, curbuf, bufsize); return handle_buffer_with<gcm_op_reader_t>(cl, curbuf, bufsize);
} }
+47 -14
View File
@@ -247,6 +247,31 @@ public:
void reset() void reset()
{ {
from = cl->write_op_pos; from = cl->write_op_pos;
init_ctx(msgr, cl);
}
static void init_ctx(osd_messenger_t* msgr, osd_client_t *cl)
{
if (!cl->enc_ctx)
{
if (msgr->encrypt_gcm_pool.size())
{
cl->enc_ctx = msgr->encrypt_gcm_pool.back();
msgr->encrypt_gcm_pool.pop_back();
}
else
{
cl->enc_ctx = EVP_CIPHER_CTX_new();
assert(cl->enc_ctx);
int r = EVP_EncryptInit_ex(cl->enc_ctx, EVP_aes_256_gcm(), NULL, NULL, NULL);
if (r != 1)
{
fprintf(stderr, "EncryptInit error: ");
ERR_print_errors_fp(stderr);
abort();
}
}
}
uint8_t iv[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; uint8_t iv[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
int r = EVP_EncryptInit_ex(cl->enc_ctx, NULL, NULL, (uint8_t*)msgr->test_osd_aes_key.data(), iv); int r = EVP_EncryptInit_ex(cl->enc_ctx, NULL, NULL, (uint8_t*)msgr->test_osd_aes_key.data(), iv);
if (r != 1) if (r != 1)
@@ -257,6 +282,15 @@ public:
} }
} }
static void free_ctx(osd_messenger_t* msgr, osd_client_t *cl)
{
if (msgr->encrypt_gcm_pool.size() < msgr->max_cipher_pool_size)
msgr->encrypt_gcm_pool.push_back(cl->enc_ctx);
else
EVP_CIPHER_CTX_free(cl->enc_ctx);
cl->enc_ctx = NULL;
}
bool write(uint8_t *src, size_t src_len, int flags) override bool write(uint8_t *src, size_t src_len, int flags) override
{ {
if (from >= src_len) if (from >= src_len)
@@ -346,11 +380,16 @@ public:
memcpy(curbuf+done, cl->enc_tag+16-cl->enc_tag_size, n); memcpy(curbuf+done, cl->enc_tag+16-cl->enc_tag_size, n);
done += n; done += n;
cl->enc_tag_size -= n; cl->enc_tag_size -= n;
return !cl->enc_tag_size; if (cl->enc_tag_size > 0)
return false;
} }
// The whole tag fits at once else
write_tag_to(cl, curbuf+done); {
done += 16; // The whole tag fits at once
write_tag_to(cl, curbuf+done);
done += 16;
}
free_ctx(msgr, cl);
return true; return true;
} }
@@ -417,16 +456,9 @@ public:
from = cl->write_op_pos; from = cl->write_op_pos;
enc_size = 0; enc_size = 0;
done_enc = 0; done_enc = 0;
if (cl->enc_ctx) if (cl->gcm_enabled)
{ {
uint8_t iv[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; gcm_op_writer_t::init_ctx(msgr, cl);
int r = EVP_EncryptInit_ex(cl->enc_ctx, NULL, NULL, (uint8_t*)msgr->test_osd_aes_key.data(), iv);
if (r != 1)
{
fprintf(stderr, "EncryptInit error: ");
ERR_print_errors_fp(stderr);
abort();
}
} }
} }
@@ -551,6 +583,7 @@ public:
// FIXME coalesce entries in ssl_out_buf // FIXME coalesce entries in ssl_out_buf
cl->send_list.push_back((iovec){ .iov_base = cl->ssl_out_buf+cl->ssl_out_buf_size, .iov_len = 16 }); cl->send_list.push_back((iovec){ .iov_base = cl->ssl_out_buf+cl->ssl_out_buf_size, .iov_len = 16 });
cl->ssl_out_buf_size += 16; cl->ssl_out_buf_size += 16;
gcm_op_writer_t::free_ctx(msgr, cl);
} }
return true; return true;
} }
@@ -742,7 +775,7 @@ bool osd_messenger_t::try_send(osd_client_t *cl)
size_t osd_messenger_t::copy_ops_to(osd_client_t *cl, uint8_t *dst, size_t dst_len) size_t osd_messenger_t::copy_ops_to(osd_client_t *cl, uint8_t *dst, size_t dst_len)
{ {
if (cl->enc_ctx) if (cl->gcm_enabled)
{ {
return copy_ops_to_with<gcm_op_writer_t>(cl, dst, dst_len); return copy_ops_to_with<gcm_op_writer_t>(cl, dst, dst_len);
} }
+10 -10
View File
@@ -83,21 +83,21 @@ void osd_messenger_t::stop_client(uint64_t client_id, bool force_delete)
fprintf(stderr, "[OSD %ju] Stopping client %ju (regular client)\n", osd_num, client_id); fprintf(stderr, "[OSD %ju] Stopping client %ju (regular client)\n", osd_num, client_id);
} }
} }
if (cl->encrypt_ctx) if (cl->xts_enc_ctx)
{ {
if (encrypt_ctx_pool.size() > max_aes_xts_pool_size) if (encrypt_xts_pool.size() > max_cipher_pool_size)
destroy_aes_xts_encrypt(cl->encrypt_ctx); destroy_aes_xts_encrypt(cl->xts_enc_ctx);
else else
encrypt_ctx_pool.push_back(cl->encrypt_ctx); encrypt_xts_pool.push_back(cl->xts_enc_ctx);
cl->encrypt_ctx = NULL; cl->xts_enc_ctx = NULL;
} }
if (cl->decrypt_ctx) if (cl->xts_dec_ctx)
{ {
if (decrypt_ctx_pool.size() > max_aes_xts_pool_size) if (decrypt_xts_pool.size() > max_cipher_pool_size)
destroy_aes_xts_decrypt(cl->decrypt_ctx); destroy_aes_xts_decrypt(cl->xts_dec_ctx);
else else
decrypt_ctx_pool.push_back(cl->decrypt_ctx); decrypt_xts_pool.push_back(cl->xts_dec_ctx);
cl->decrypt_ctx = NULL; cl->xts_dec_ctx = NULL;
} }
// First set state to STOPPED so another stop_client() call doesn't try to free it again // First set state to STOPPED so another stop_client() call doesn't try to free it again
cl->refs++; cl->refs++;