Add support for full AES-GCM including double encryption of AES-XTS :D

This commit is contained in:
Vitaliy Filippov
2026-07-05 14:58:24 +03:00
parent 784fd7d233
commit a5dbf74123
16 changed files with 358 additions and 245 deletions
+18
View File
@@ -792,6 +792,24 @@ jobs:
echo "" echo ""
done done
test_snapshot_chain_enc_gcm:
runs-on: ubuntu-latest
needs: build
container: ${{env.TEST_IMAGE}}:${{github.sha}}
steps:
- name: Run test
id: test
timeout-minutes: 3
run: TEST_NAME=enc_gcm ENCRYPTED=1 VITASTOR_CFG=',"proto_checksums":"gcm"' /root/vitastor/tests/test_snapshot_chain.sh
- name: Print logs
if: always() && steps.test.outcome == 'failure'
run: |
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
echo "-------- $i --------"
cat $i
echo ""
done
test_old_snapshot_chain: test_old_snapshot_chain:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: build
+40 -16
View File
@@ -197,19 +197,34 @@ osd_messenger_t::~osd_messenger_t()
destroy_tls(); destroy_tls();
} }
static int parse_proto_checksums(const json11::Json & val, int default_value)
{
if (val.is_string())
{
const auto & str = val.string_value();
if (str == "full")
return MSGR_CSUM_FULL;
else if (str == "payload")
return MSGR_CSUM_PAYLOAD;
else if (str == "gcm")
return MSGR_CSUM_GCM;
else if (str == "none")
return 0;
else if (str == "")
return default_value;
}
else if (val.is_null())
return default_value;
fprintf(stderr, "proto_checksums should be \"full\", \"payload\", \"gcm\", \"none\""
", \"\" or null (default), but it is: %s\n", val.dump().c_str());
exit(1);
}
void osd_messenger_t::parse_config(const json11::Json & config, bool init) void osd_messenger_t::parse_config(const json11::Json & config, bool init)
{ {
this->max_cipher_pool_size = config["max_cipher_pool_size"].uint64_value(); this->max_cipher_pool_size = config["max_cipher_pool_size"].uint64_value();
if (!this->max_cipher_pool_size) if (!this->max_cipher_pool_size)
this->max_cipher_pool_size = 256; this->max_cipher_pool_size = 256;
if (config["proto_checksums"].is_null())
this->use_proto_checksums = MSGR_CSUM_PAYLOAD;
else if (config["proto_checksums"].is_bool())
this->use_proto_checksums = config["proto_checksums"].bool_value() ? MSGR_CSUM_FULL : 0;
else if (config["proto_checksums"].string_value() != "")
this->use_proto_checksums = config["proto_checksums"].string_value() == "full" ? MSGR_CSUM_FULL : MSGR_CSUM_PAYLOAD;
else
this->use_proto_checksums = 0;
this->receive_buffer_size = (uint32_t)config["tcp_header_buffer_size"].uint64_value(); this->receive_buffer_size = (uint32_t)config["tcp_header_buffer_size"].uint64_value();
if (!this->receive_buffer_size || this->receive_buffer_size > 1024*1024*1024) if (!this->receive_buffer_size || this->receive_buffer_size > 1024*1024*1024)
this->receive_buffer_size = 65536; this->receive_buffer_size = 65536;
@@ -275,6 +290,8 @@ void osd_messenger_t::parse_config(const json11::Json & config, bool init)
osd_tls_ca = config["osd_ca"].string_value(); osd_tls_ca = config["osd_ca"].string_value();
client_tls_ca = config["client_ca"].string_value(); client_tls_ca = config["client_ca"].string_value();
} }
this->use_proto_checksums = parse_proto_checksums(config["proto_checksums"], MSGR_CSUM_PAYLOAD);
this->force_proto_checksums = parse_proto_checksums(config["force_proto_checksums"], tls_cert != "" ? MSGR_CSUM_PAYLOAD : 0);
if (!osd_num) if (!osd_num)
this->iothread_count = (uint32_t)config["client_iothread_count"].uint64_value(); this->iothread_count = (uint32_t)config["client_iothread_count"].uint64_value();
else else
@@ -653,6 +670,21 @@ void osd_messenger_t::check_peer_config(osd_client_t *cl)
err = !check_config_hook(cl, config); err = !check_config_hook(cl, config);
} }
} }
if (!err && use_proto_checksums)
{
auto peer_csums = config["features"]["proto_checksums"].uint64_value();
if (peer_csums == MSGR_CSUM_GCM && use_proto_checksums == MSGR_CSUM_GCM && cl->gcm_enabled)
cl->proto_csum_status = MSGR_CSUM_GCM;
else if (peer_csums == MSGR_CSUM_FULL && use_proto_checksums == MSGR_CSUM_FULL)
cl->proto_csum_status = MSGR_CSUM_FULL;
else if (peer_csums && use_proto_checksums)
cl->proto_csum_status = MSGR_CSUM_PAYLOAD;
if (cl->proto_csum_status < force_proto_checksums)
{
fprintf(stderr, "Error: OSD %ju use_proto_checksums security level is lower than force_proto_checksums\n", cl->osd_num);
err = true;
}
}
if (err) if (err)
{ {
osd_num_t peer_osd = cl->osd_num; osd_num_t peer_osd = cl->osd_num;
@@ -661,14 +693,6 @@ void osd_messenger_t::check_peer_config(osd_client_t *cl)
delete op; delete op;
return; return;
} }
if (use_proto_checksums)
{
auto peer_csums = config["features"]["proto_checksums"].uint64_value();
if (peer_csums == MSGR_CSUM_FULL && use_proto_checksums == MSGR_CSUM_FULL)
cl->proto_csum_status = MSGR_CSUM_FULL;
else if (peer_csums && use_proto_checksums)
cl->proto_csum_status = MSGR_CSUM_PAYLOAD;
}
#ifdef WITH_RDMA #ifdef WITH_RDMA
if (!use_rdmacm && cl->rdma_conn && config["rdma_address"].is_string()) if (!use_rdmacm && cl->rdma_conn && config["rdma_address"].is_string())
{ {
+3 -4
View File
@@ -41,7 +41,8 @@
#define MSGR_CSUM_PAYLOAD 1 #define MSGR_CSUM_PAYLOAD 1
#define MSGR_CSUM_FULL 2 #define MSGR_CSUM_FULL 2
#define MSGR_CSUM_NEG 4 #define MSGR_CSUM_GCM 4
#define MSGR_CSUM_NEG 8
#define VITASTOR_CONFIG_PATH "/etc/vitastor/vitastor.conf" #define VITASTOR_CONFIG_PATH "/etc/vitastor/vitastor.conf"
@@ -92,9 +93,6 @@ struct osd_client_t
msgr_rdma_connection_t *rdma_conn = NULL; msgr_rdma_connection_t *rdma_conn = NULL;
#endif #endif
uint8_t *ssl_out_buf = NULL;
size_t ssl_out_buf_size = 0, ssl_out_buf_cap = 0;
bool gcm_enabled = false; bool gcm_enabled = false;
msgr_handshake_i *hs = NULL; msgr_handshake_i *hs = NULL;
msgr_handshake_result_t hs_result; msgr_handshake_result_t hs_result;
@@ -290,6 +288,7 @@ public:
std::vector<std::string> all_osd_networks; std::vector<std::string> all_osd_networks;
std::vector<addr_mask_t> all_osd_network_masks; std::vector<addr_mask_t> all_osd_network_masks;
int use_proto_checksums = 0; int use_proto_checksums = 0;
int force_proto_checksums = 0;
// op statistics // op statistics
osd_op_stats_t stats, recovery_stats; osd_op_stats_t stats, recovery_stats;
+68 -8
View File
@@ -44,9 +44,10 @@ op_aes_xts_encrypt_t::~op_aes_xts_encrypt_t()
free(tmp); free(tmp);
} }
void op_aes_xts_encrypt_t::start(uint8_t *key, uint64_t start_offset, size_t block_size) void op_aes_xts_encrypt_t::start(osd_client_t *cl, uint8_t *key, uint64_t start_offset, size_t block_size)
{ {
assert(!encrypted); assert(!encrypted);
this->cl = cl;
this->start_offset = start_offset; this->start_offset = start_offset;
this->key = key; this->key = key;
this->block_size = block_size; this->block_size = block_size;
@@ -91,6 +92,28 @@ void op_aes_xts_encrypt_t::encrypt_block(uint8_t *in, uint8_t *out)
#endif #endif
} }
static inline void copy_or_gcm(osd_client_t *cl, uint8_t *out, uint8_t *in, size_t n)
{
if (cl->proto_csum_status != MSGR_CSUM_GCM)
memcpy(out, in, n);
else
{
#ifdef WITH_ISAL_CRYPTO
int r = isal_aes_gcm_enc_256_update(&cl->my_key_isal, cl->enc_ctx, out, in, n);
assert(!r);
#else
int actual_out;
if (EVP_EncryptUpdate(cl->enc_ctx, out, &actual_out, in, n) != 1)
{
fprintf(stderr, "EncryptUpdate error: ");
ERR_print_errors_fp(stderr);
abort();
}
assert(actual_out == n);
#endif
}
}
void op_aes_xts_encrypt_t::update(uint8_t *in, size_t max_in, uint8_t *out, size_t max_out, size_t & done_in, size_t & done_out) void op_aes_xts_encrypt_t::update(uint8_t *in, size_t max_in, uint8_t *out, size_t max_out, size_t & done_in, size_t & done_out)
{ {
// Fucking AES-XTS implementations (all of them) don't have streaming support, // Fucking AES-XTS implementations (all of them) don't have streaming support,
@@ -104,7 +127,7 @@ void op_aes_xts_encrypt_t::update(uint8_t *in, size_t max_in, uint8_t *out, size
assert(tmp); assert(tmp);
if (max_out > block_size - tmp_pos) if (max_out > block_size - tmp_pos)
max_out = block_size - tmp_pos; max_out = block_size - tmp_pos;
memcpy(out, tmp + tmp_pos, max_out); copy_or_gcm(cl, out, tmp + tmp_pos, max_out);
done_out += max_out; done_out += max_out;
tmp_pos += max_out; tmp_pos += max_out;
if (tmp_pos >= block_size) if (tmp_pos >= block_size)
@@ -137,7 +160,7 @@ void op_aes_xts_encrypt_t::update(uint8_t *in, size_t max_in, uint8_t *out, size
memcpy(tmp + offset%block_size, in, max_in); memcpy(tmp + offset%block_size, in, max_in);
encrypt_block(tmp, tmp); encrypt_block(tmp, tmp);
encrypted = true; encrypted = true;
memcpy(out, tmp, max_out); copy_or_gcm(cl, out, tmp, max_out);
tmp_pos = max_out; tmp_pos = max_out;
done_in += max_in-1; done_in += max_in-1;
offset += max_in; offset += max_in;
@@ -147,6 +170,8 @@ void op_aes_xts_encrypt_t::update(uint8_t *in, size_t max_in, uint8_t *out, size
{ {
// Full block - simplest case // Full block - simplest case
encrypt_block(in, out); encrypt_block(in, out);
if (cl->proto_csum_status == MSGR_CSUM_GCM)
copy_or_gcm(cl, out, out, block_size);
done_in += block_size; done_in += block_size;
offset += block_size; offset += block_size;
done_out += block_size; done_out += block_size;
@@ -158,6 +183,8 @@ void op_aes_xts_encrypt_t::update(uint8_t *in, size_t max_in, uint8_t *out, size
max_in = block_size - offset%block_size; max_in = block_size - offset%block_size;
memcpy(tmp + offset%block_size, in, max_in); memcpy(tmp + offset%block_size, in, max_in);
encrypt_block(tmp, out); encrypt_block(tmp, out);
if (cl->proto_csum_status == MSGR_CSUM_GCM)
copy_or_gcm(cl, out, out, block_size);
done_in += max_in; done_in += max_in;
offset += max_in; offset += max_in;
done_out += block_size; done_out += block_size;
@@ -196,9 +223,10 @@ op_aes_xts_decrypt_t::~op_aes_xts_decrypt_t()
free(tmp); free(tmp);
} }
void op_aes_xts_decrypt_t::start(uint8_t **key_chain, size_t chain_size, void *key_indexes, uint64_t start_offset, size_t block_size) void op_aes_xts_decrypt_t::start(osd_client_t *cl, uint8_t **key_chain, size_t chain_size, void *key_indexes, uint64_t start_offset, size_t block_size)
{ {
assert(!decrypted); assert(!decrypted);
this->cl = cl;
this->start_offset = start_offset; this->start_offset = start_offset;
this->key_chain = key_chain; this->key_chain = key_chain;
this->chain_size = chain_size; this->chain_size = chain_size;
@@ -269,6 +297,23 @@ void op_aes_xts_decrypt_t::decrypt_block(uint8_t *in, uint8_t *out)
#endif #endif
} }
static inline void gcm_dec(osd_client_t *cl, uint8_t *out, uint8_t *in, size_t n)
{
#ifdef WITH_ISAL_CRYPTO
int r = isal_aes_gcm_dec_256_update(&cl->peer_key_isal, cl->dec_ctx, out, in, n);
assert(!r);
#else
int actual_out;
if (EVP_DecryptUpdate(cl->dec_ctx, out, &actual_out, in, n) != 1)
{
fprintf(stderr, "DecryptUpdate error: ");
ERR_print_errors_fp(stderr);
abort();
}
assert(actual_out == n);
#endif
}
// out may be NULL, in this case all input is still decrypted to calculate checksums, // out may be NULL, in this case all input is still decrypted to calculate checksums,
// but part of it is skipped and not copied to out // but part of it is skipped and not copied to out
void op_aes_xts_decrypt_t::update(uint8_t *in, size_t max_in, uint8_t *out, size_t max_out, size_t & done_in, size_t & done_out) void op_aes_xts_decrypt_t::update(uint8_t *in, size_t max_in, uint8_t *out, size_t max_out, size_t & done_in, size_t & done_out)
@@ -316,6 +361,8 @@ void op_aes_xts_decrypt_t::update(uint8_t *in, size_t max_in, uint8_t *out, size
} }
max_in = block_size - offset%block_size; max_in = block_size - offset%block_size;
memcpy(tmp + offset%block_size, in, max_in); memcpy(tmp + offset%block_size, in, max_in);
if (cl->proto_csum_status == MSGR_CSUM_GCM)
gcm_dec(cl, tmp, tmp, block_size);
decrypt_block(tmp, tmp); decrypt_block(tmp, tmp);
decrypted = true; decrypted = true;
if (out) if (out)
@@ -328,7 +375,18 @@ void op_aes_xts_decrypt_t::update(uint8_t *in, size_t max_in, uint8_t *out, size
else if (!(offset%block_size)) else if (!(offset%block_size))
{ {
// Full block - simplest case // Full block - simplest case
if (out) if (cl->proto_csum_status == MSGR_CSUM_GCM)
{
if (!tmp)
{
tmp = (uint8_t*)malloc_or_die(block_size);
tmp_size = block_size;
}
gcm_dec(cl, tmp, in, block_size);
if (out)
decrypt_block(tmp, out);
}
else
decrypt_block(in, out); decrypt_block(in, out);
done_in += block_size; done_in += block_size;
offset += block_size; offset += block_size;
@@ -341,6 +399,8 @@ void op_aes_xts_decrypt_t::update(uint8_t *in, size_t max_in, uint8_t *out, size
max_in = block_size - offset%block_size; max_in = block_size - offset%block_size;
memcpy(tmp + offset%block_size, in, max_in); memcpy(tmp + offset%block_size, in, max_in);
assert(out); assert(out);
if (cl->proto_csum_status == MSGR_CSUM_GCM)
gcm_dec(cl, tmp, tmp, block_size);
decrypt_block(tmp, out); decrypt_block(tmp, out);
done_in += max_in; done_in += max_in;
offset += max_in; offset += max_in;
@@ -365,7 +425,7 @@ void osd_messenger_t::op_encrypted_copy_buf(osd_client_t *cl, uint8_t *enc_buf,
else else
cl->xts_enc_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->xts_enc_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, cl->write_op->enc->key_chain[0], cl->write_op->req.rw.offset, cl->write_op->enc->bitmap_granularity);
} }
while (done_plain < plain_len && done_enc < enc_len) while (done_plain < plain_len && done_enc < enc_len)
{ {
@@ -411,7 +471,7 @@ void osd_messenger_t::op_decrypt_start(osd_client_t* cl)
cl->xts_dec_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->xts_dec_ctx->start(enc->key_chain, enc->chain_size, cl->xts_dec_ctx->start(cl, 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);
} }
@@ -561,7 +621,7 @@ void osd_messenger_t::init_tls_client(osd_client_t *cl)
cl->gcm_enabled = true; cl->gcm_enabled = true;
cl->hs = hs_ctx->create(); cl->hs = hs_ctx->create();
cl->hs->init(cl->is_incoming); cl->hs->init(cl->is_incoming);
if (cl->hs->get_out().size()) if (cl->hs->out_size())
{ {
if (cl->write_state == 0) if (cl->write_state == 0)
{ {
+6 -2
View File
@@ -12,11 +12,14 @@
#include <openssl/evp.h> #include <openssl/evp.h>
#include <openssl/err.h> #include <openssl/err.h>
struct osd_client_t;
class op_aes_xts_encrypt_t class op_aes_xts_encrypt_t
{ {
#ifndef WITH_ISAL_CRYPTO #ifndef WITH_ISAL_CRYPTO
EVP_CIPHER_CTX *ctx = NULL; EVP_CIPHER_CTX *ctx = NULL;
#endif #endif
osd_client_t *cl = NULL;
uint64_t start_offset = 0; uint64_t start_offset = 0;
uint8_t *key = NULL; uint8_t *key = NULL;
size_t offset = 0; size_t offset = 0;
@@ -32,7 +35,7 @@ public:
op_aes_xts_encrypt_t(); op_aes_xts_encrypt_t();
~op_aes_xts_encrypt_t(); ~op_aes_xts_encrypt_t();
void start(uint8_t *key, uint64_t start_offset, size_t block_size); void start(osd_client_t *cl, uint8_t *key, uint64_t start_offset, size_t block_size);
void update(uint8_t *in, size_t max_in, uint8_t *out, size_t max_out, size_t & done_in, size_t & done_out); void update(uint8_t *in, size_t max_in, uint8_t *out, size_t max_out, size_t & done_in, size_t & done_out);
}; };
@@ -43,6 +46,7 @@ class op_aes_xts_decrypt_t
#ifndef WITH_ISAL_CRYPTO #ifndef WITH_ISAL_CRYPTO
EVP_CIPHER_CTX *ctx = NULL; EVP_CIPHER_CTX *ctx = NULL;
#endif #endif
osd_client_t *cl = NULL;
uint64_t start_offset = 0; uint64_t start_offset = 0;
uint8_t **key_chain = NULL; uint8_t **key_chain = NULL;
size_t chain_size = 0; size_t chain_size = 0;
@@ -61,7 +65,7 @@ public:
op_aes_xts_decrypt_t(); op_aes_xts_decrypt_t();
~op_aes_xts_decrypt_t(); ~op_aes_xts_decrypt_t();
void start(uint8_t **key_chain, size_t chain_size, void *key_indexes, uint64_t start_offset, size_t block_size); void start(osd_client_t *cl, uint8_t **key_chain, size_t chain_size, void *key_indexes, uint64_t start_offset, size_t block_size);
void update(uint8_t *in, size_t max_in, uint8_t *out, size_t max_out, size_t & done_in, size_t & done_out); void update(uint8_t *in, size_t max_in, uint8_t *out, size_t max_out, size_t & done_in, size_t & done_out);
}; };
+56 -11
View File
@@ -18,6 +18,7 @@
#include <openssl/err.h> #include <openssl/err.h>
#include "msgr_handshake.h" #include "msgr_handshake.h"
#include "malloc_or_die.h"
#include "openssl_util.h" #include "openssl_util.h"
#include "str_util.h" #include "str_util.h"
@@ -84,7 +85,8 @@ class msgr_handshake_t: public msgr_handshake_i
std::vector<uint8_t> full_handshake; std::vector<uint8_t> full_handshake;
std::vector<uint8_t> in_buf; std::vector<uint8_t> in_buf;
std::vector<uint8_t> out_buf; uint8_t *out_buf = NULL;
size_t out_buf_size = 0;
std::string error; std::string error;
int state = 0; int state = 0;
@@ -125,7 +127,10 @@ public:
bool init(bool server_mode) override; bool init(bool server_mode) override;
ssize_t handle(uint8_t* in_buf, size_t in_size) override; ssize_t handle(uint8_t* in_buf, size_t in_size) override;
bool done() override; bool done() override;
std::vector<uint8_t>& get_out() override; uint8_t *get_out() override;
size_t out_size() override;
void eat_out(size_t n) override;
void reset_out() override;
msgr_handshake_result_t get_result() override; msgr_handshake_result_t get_result() override;
std::string get_error() override; std::string get_error() override;
}; };
@@ -247,6 +252,8 @@ bool msgr_handshake_ctx_t::derive_kdf(const uint8_t* insecret, size_t insecret_l
msgr_handshake_t::~msgr_handshake_t() msgr_handshake_t::~msgr_handshake_t()
{ {
if (out_buf)
free(out_buf);
if (peer_cert) if (peer_cert)
X509_free(peer_cert); X509_free(peer_cert);
if (ec_key) if (ec_key)
@@ -288,6 +295,12 @@ static void copy_to(std::vector<uint8_t> & buf, const void* src, uint32_t len)
memcpy(buf.data() + old_size, src, len); memcpy(buf.data() + old_size, src, len);
} }
static void copy_to_raw(uint8_t* & buf, const void* src, size_t len)
{
memcpy(buf, src, len);
buf += len;
}
static void copy_to_with_len(std::vector<uint8_t> & buf, const void* src, uint32_t len) static void copy_to_with_len(std::vector<uint8_t> & buf, const void* src, uint32_t len)
{ {
copy_to(buf, &len, sizeof(len)); copy_to(buf, &len, sizeof(len));
@@ -442,9 +455,10 @@ bool msgr_handshake_t::make_client_init()
size_t key_len = EVP_PKEY_get1_encoded_public_key(ec_key, &key); size_t key_len = EVP_PKEY_get1_encoded_public_key(ec_key, &key);
if (!key_len) if (!key_len)
return on_error("EVP_PKEY_get1_encoded_public_key: "); return on_error("EVP_PKEY_get1_encoded_public_key: ");
const size_t old_len = out_buf.size(); const size_t old_out_size = out_buf_size;
out_buf.resize(out_buf.size() + key_len + sizeof(msgr_handshake_hdr_t)); out_buf_size += key_len + sizeof(msgr_handshake_hdr_t);
uint8_t *buf = out_buf.data() + old_len; out_buf = (uint8_t*)realloc_or_die(out_buf, out_buf_size);
uint8_t *buf = out_buf + old_out_size;
msgr_handshake_hdr_t *hdr = (msgr_handshake_hdr_t *)buf; msgr_handshake_hdr_t *hdr = (msgr_handshake_hdr_t *)buf;
hdr->msg_len = key_len + sizeof(msgr_handshake_hdr_t); hdr->msg_len = key_len + sizeof(msgr_handshake_hdr_t);
hdr->magic = MSGR_HS_MAGIC; hdr->magic = MSGR_HS_MAGIC;
@@ -485,9 +499,12 @@ bool msgr_handshake_t::make_server_reply()
} }
// Construct message // Construct message
hdr.msg_len = sizeof(msgr_handshake_hdr_t) + 4 + key_len + encrypt_data.size(); hdr.msg_len = sizeof(msgr_handshake_hdr_t) + 4 + key_len + encrypt_data.size();
copy_to(out_buf, &hdr, sizeof(hdr)); out_buf = (uint8_t*)realloc_or_die(out_buf, (out_buf_size += hdr.msg_len));
copy_to_with_len(out_buf, key, key_len); uint8_t *cur = out_buf + out_buf_size - hdr.msg_len;
copy_to(out_buf, encrypt_data.data(), encrypt_data.size()); copy_to_raw(cur, &hdr, sizeof(hdr));
copy_to_raw(cur, &key_len, 4);
copy_to_raw(cur, key, key_len);
copy_to_raw(cur, encrypt_data.data(), encrypt_data.size());
OPENSSL_free(key); OPENSSL_free(key);
return true; return true;
} }
@@ -510,8 +527,10 @@ bool msgr_handshake_t::make_client_reply()
return false; return false;
// Construct message // Construct message
hdr.msg_len = sizeof(msgr_handshake_hdr_t) + encrypt_data.size(); hdr.msg_len = sizeof(msgr_handshake_hdr_t) + encrypt_data.size();
copy_to(out_buf, &hdr, sizeof(hdr)); out_buf = (uint8_t*)realloc_or_die(out_buf, (out_buf_size += hdr.msg_len));
copy_to(out_buf, encrypt_data.data(), encrypt_data.size()); uint8_t *cur = out_buf + out_buf_size - hdr.msg_len;
copy_to_raw(cur, &hdr, sizeof(hdr));
copy_to_raw(cur, encrypt_data.data(), encrypt_data.size());
return true; return true;
} }
@@ -742,11 +761,37 @@ bool msgr_handshake_t::done()
return (state == MSGR_HS_DONE); return (state == MSGR_HS_DONE);
} }
std::vector<uint8_t>& msgr_handshake_t::get_out() uint8_t *msgr_handshake_t::get_out()
{ {
return out_buf; return out_buf;
} }
size_t msgr_handshake_t::out_size()
{
return out_buf_size;
}
void msgr_handshake_t::eat_out(size_t n)
{
if (n >= out_buf_size)
{
free(out_buf);
out_buf = NULL;
out_buf_size = 0;
}
else
{
memmove(out_buf, out_buf + n, out_buf_size - n);
out_buf_size -= n;
}
}
void msgr_handshake_t::reset_out()
{
out_buf = NULL;
out_buf_size = 0;
}
msgr_handshake_result_t msgr_handshake_t::get_result() msgr_handshake_result_t msgr_handshake_t::get_result()
{ {
if (state != MSGR_HS_DONE) if (state != MSGR_HS_DONE)
+4 -1
View File
@@ -35,7 +35,10 @@ public:
virtual bool init(bool server_mode) = 0; virtual bool init(bool server_mode) = 0;
virtual ssize_t handle(uint8_t* in_buf, size_t in_size) = 0; virtual ssize_t handle(uint8_t* in_buf, size_t in_size) = 0;
virtual bool done() = 0; virtual bool done() = 0;
virtual std::vector<uint8_t> & get_out() = 0; virtual uint8_t *get_out() = 0;
virtual size_t out_size() = 0;
virtual void eat_out(size_t n) = 0;
virtual void reset_out() = 0;
virtual msgr_handshake_result_t get_result() = 0; virtual msgr_handshake_result_t get_result() = 0;
virtual std::string get_error() = 0; virtual std::string get_error() = 0;
}; };
-4
View File
@@ -24,10 +24,6 @@ osd_op_t::~osd_op_t()
// So we don't reuse it, but free it every time // So we don't reuse it, but free it every time
free(buf); free(buf);
} }
if (enc_buf)
{
free(enc_buf);
}
} }
bool osd_op_t::is_recovery_related() bool osd_op_t::is_recovery_related()
-1
View File
@@ -186,7 +186,6 @@ struct __attribute__((visibility("default"))) osd_op_t
uint8_t *bitmap_buf = NULL; uint8_t *bitmap_buf = NULL;
void *rmw_buf = NULL; void *rmw_buf = NULL;
std::shared_ptr<osd_op_enc_t> enc; std::shared_ptr<osd_op_enc_t> enc;
uint8_t *enc_buf = NULL;
uint64_t csum = 0; // network layer checksum uint64_t csum = 0; // network layer checksum
osd_primary_op_data_t* op_data = NULL; osd_primary_op_data_t* op_data = NULL;
std::function<void(osd_op_t*)> callback; std::function<void(osd_op_t*)> callback;
+5 -2
View File
@@ -735,9 +735,12 @@ void osd_messenger_t::handle_rdma_events(msgr_rdma_context_t *rdma_context)
if (rc->send_done_pos == rc->send_out_size) if (rc->send_done_pos == rc->send_out_size)
rc->send_done_pos = 0; rc->send_done_pos = 0;
assert(rc->send_done_pos < rc->send_out_size); assert(rc->send_done_pos < rc->send_out_size);
while (cl->send_free_ops.front()) while (osd_op_t *op = cl->send_free_ops.front())
{ {
delete cl->send_free_ops.front(); if (!((size_t)op & 7))
delete op;
else
free((void*)((size_t)op & ~(size_t)7));
cl->send_free_ops.pop_front(); cl->send_free_ops.pop_front();
} }
cl->send_free_ops.pop_front(); cl->send_free_ops.pop_front();
+28 -40
View File
@@ -170,41 +170,17 @@ public:
if (done >= bufsize) if (done >= bufsize)
return false; return false;
size_t n = dst_len-from; size_t n = dst_len-from;
if (!(flags & RDR_GCM)) if (n > bufsize-done)
n = bufsize-done;
if (flags & RDR_XTS)
{ {
if (n > bufsize-done) msgr->op_decrypted_copy_buf(cl, curbuf, bufsize, dst, dst_len, from, done);
n = bufsize-done; n = 0;
if (flags & RDR_XTS)
{
msgr->op_decrypted_copy_buf(cl, curbuf, bufsize, dst, dst_len, from, done);
n = 0;
}
else
{
if (cl->read_csum_state && !(flags & RDR_NO_CSUM))
{
// data may be skipped if dst == NULL but checksum is still calculated
XXH3_64bits_update(cl->read_csum_state, curbuf+done, n);
}
// Here, dst == NULL is allowed
if (dst != NULL)
memcpy(dst+from, curbuf+done, n);
done += n;
}
cl->read_op_pos += n;
from += n;
if (from < dst_len)
{
return false;
}
} }
else else if (flags & RDR_GCM)
{ {
// Here, dst == NULL is not allowed // Here, dst == NULL is not allowed
assert(dst != NULL); assert(dst != NULL);
size_t n = dst_len-from;
if (n > bufsize-done)
n = bufsize-done;
#ifdef WITH_ISAL_CRYPTO #ifdef WITH_ISAL_CRYPTO
int r = isal_aes_gcm_dec_256_update(&cl->peer_key_isal, cl->dec_ctx, dst+from, curbuf+done, n); int r = isal_aes_gcm_dec_256_update(&cl->peer_key_isal, cl->dec_ctx, dst+from, curbuf+done, n);
assert(!r); assert(!r);
@@ -223,12 +199,24 @@ public:
XXH3_64bits_update(cl->read_csum_state, dst+from, n); XXH3_64bits_update(cl->read_csum_state, dst+from, n);
} }
done += n; done += n;
from += n; }
cl->read_op_pos += n; else
if (from < dst_len) {
if (cl->read_csum_state && !(flags & RDR_NO_CSUM))
{ {
return false; // data may be skipped if dst == NULL but checksum is still calculated
XXH3_64bits_update(cl->read_csum_state, curbuf+done, n);
} }
// Here, dst == NULL is allowed
if (dst != NULL)
memcpy(dst+from, curbuf+done, n);
done += n;
}
cl->read_op_pos += n;
from += n;
if (from < dst_len)
{
return false;
} }
from = 0; from = 0;
return true; return true;
@@ -605,7 +593,7 @@ bool osd_messenger_t::handle_read_buffer(osd_client_t *cl, uint8_t *curbuf, size
} }
curbuf += done; curbuf += done;
bufsize -= done; bufsize -= done;
if (cl->hs->get_out().size()) if (cl->hs->out_size())
{ {
if (cl->write_state == 0) if (cl->write_state == 0)
{ {
@@ -613,7 +601,7 @@ bool osd_messenger_t::handle_read_buffer(osd_client_t *cl, uint8_t *curbuf, size
write_ready_clients.push_back(cl->client_id); write_ready_clients.push_back(cl->client_id);
} }
} }
if (cl->hs->done() && !cl->hs->get_out().size()) if (cl->hs->done() && !cl->hs->out_size())
{ {
// Delete hs when done and nothing to send // Delete hs when done and nothing to send
delete cl->hs; delete cl->hs;
@@ -933,7 +921,7 @@ bool osd_messenger_t::op_read_from(osd_client_t *cl, msgr_op_reader_t & rdr)
{ {
if (!rdr.read((uint8_t*)op->bitmap, op->req.sec_rw.attr_len, RDR_GCM)) if (!rdr.read((uint8_t*)op->bitmap, op->req.sec_rw.attr_len, RDR_GCM))
return false; return false;
if (!rdr.read((uint8_t*)op->buf, op->req.sec_rw.len, 0)) if (!rdr.read((uint8_t*)op->buf, op->req.sec_rw.len, cl->proto_csum_status == MSGR_CSUM_GCM ? RDR_GCM : 0))
return false; return false;
} }
else if (op->req.hdr.opcode == OSD_OP_SEC_STABILIZE || else if (op->req.hdr.opcode == OSD_OP_SEC_STABILIZE ||
@@ -949,7 +937,7 @@ bool osd_messenger_t::op_read_from(osd_client_t *cl, msgr_op_reader_t & rdr)
} }
else if (op->req.hdr.opcode == OSD_OP_WRITE) else if (op->req.hdr.opcode == OSD_OP_WRITE)
{ {
if (!rdr.read((uint8_t*)op->buf, op->req.rw.len, 0)) if (!rdr.read((uint8_t*)op->buf, op->req.rw.len, cl->proto_csum_status == MSGR_CSUM_GCM ? RDR_GCM : 0))
return false; return false;
} }
else if (op->req.hdr.opcode == OSD_OP_SHOW_CONFIG) else if (op->req.hdr.opcode == OSD_OP_SHOW_CONFIG)
@@ -973,7 +961,7 @@ switched_type:
if (op->reply.hdr.retval > 0) if (op->reply.hdr.retval > 0)
{ {
for (int i = 0; i < op->iov.count; i++) for (int i = 0; i < op->iov.count; i++)
if (!rdr.read((uint8_t*)op->iov.buf[i].iov_base, op->iov.buf[i].iov_len, 0)) if (!rdr.read((uint8_t*)op->iov.buf[i].iov_base, op->iov.buf[i].iov_len, (cl->proto_csum_status == MSGR_CSUM_GCM ? RDR_GCM : 0)))
return false; return false;
} }
} }
@@ -987,7 +975,7 @@ switched_type:
if (op->reply.hdr.retval > 0) if (op->reply.hdr.retval > 0)
{ {
for (int i = 0; i < op->iov.count; i++) for (int i = 0; i < op->iov.count; i++)
if (!rdr.read((uint8_t*)op->iov.buf[i].iov_base, op->iov.buf[i].iov_len, (op->enc ? RDR_XTS : 0))) if (!rdr.read((uint8_t*)op->iov.buf[i].iov_base, op->iov.buf[i].iov_len, (op->enc ? RDR_XTS : 0) | (cl->proto_csum_status == MSGR_CSUM_GCM ? RDR_GCM : 0)))
return false; return false;
} }
} }
+102 -138
View File
@@ -15,6 +15,8 @@
#define WR_XTS 2 #define WR_XTS 2
#define WR_NO_CSUM 4 #define WR_NO_CSUM 4
#define GCM_TMP_BUF_SIZE 4096
class msgr_op_writer_t class msgr_op_writer_t
{ {
public: public:
@@ -180,28 +182,11 @@ public:
from -= src_len; from -= src_len;
return true; return true;
} }
if (!(flags & WR_GCM)) if (flags & WR_XTS)
{ {
if (flags & WR_XTS) msgr->op_encrypted_copy_buf(cl, curbuf, bufsize, src, src_len, from, done);
{
msgr->op_encrypted_copy_buf(cl, curbuf, bufsize, src, src_len, from, done);
}
else
{
size_t n = src_len-from;
if (n > bufsize-done)
n = bufsize-done;
if (!n)
return false;
if (cl->write_csum_state && !(flags & WR_NO_CSUM))
XXH3_64bits_update(cl->write_csum_state, src+from, n);
memcpy(curbuf+done, src+from, n);
done += n;
cl->write_op_pos += n;
from += n;
}
} }
else else if (flags & WR_GCM)
{ {
size_t n = src_len-from; size_t n = src_len-from;
if (n > bufsize-done) if (n > bufsize-done)
@@ -227,6 +212,20 @@ public:
cl->write_op_pos += n; cl->write_op_pos += n;
from += n; from += n;
} }
else
{
size_t n = src_len-from;
if (n > bufsize-done)
n = bufsize-done;
if (!n)
return false;
if (cl->write_csum_state && !(flags & WR_NO_CSUM))
XXH3_64bits_update(cl->write_csum_state, src+from, n);
memcpy(curbuf+done, src+from, n);
done += n;
cl->write_op_pos += n;
from += n;
}
if (from < src_len) if (from < src_len)
return false; return false;
from = 0; from = 0;
@@ -297,63 +296,49 @@ class get_op_writer_t: public msgr_op_writer_t
osd_client_t* cl; osd_client_t* cl;
size_t from; size_t from;
size_t done; size_t done;
size_t op_enc;
size_t enc_size; size_t enc_size;
size_t done_enc; size_t done_enc;
uint8_t *enc_buf;
public: public:
get_op_writer_t(osd_messenger_t* msgr, osd_client_t* cl, uint8_t*, size_t): get_op_writer_t(osd_messenger_t* msgr, osd_client_t* cl, uint8_t*, size_t):
msgr(msgr), cl(cl), from(cl->write_op_pos), done(0), enc_size(0), done_enc(0) msgr(msgr), cl(cl), from(cl->write_op_pos), done(0), enc_size(0), done_enc(0), enc_buf(NULL)
{ {
} }
static void ssl_extend_buf(osd_client_t *cl, size_t more = 0)
{
size_t min_cap = cl->ssl_out_buf_size*2;
if (min_cap < cl->ssl_out_buf_size+more)
min_cap = cl->ssl_out_buf_size+more;
if (min_cap < 16384)
min_cap = 16384;
if (cl->ssl_out_buf_cap < min_cap)
{
uintptr_t old_buf = (uintptr_t)cl->ssl_out_buf;
uintptr_t old_end = old_buf + cl->ssl_out_buf_cap;
cl->ssl_out_buf = (uint8_t*)realloc_or_die(cl->ssl_out_buf, min_cap);
cl->ssl_out_buf_cap = min_cap;
for (auto & iov: cl->send_list)
{
if ((uintptr_t)iov.iov_base >= old_buf && (uintptr_t)iov.iov_base < old_end)
iov.iov_base = cl->ssl_out_buf + ((uintptr_t)iov.iov_base - old_buf);
}
}
}
static void send_out_buf(osd_client_t *cl, size_t n)
{
if (cl->send_list.size() > 0)
{
iovec& last = cl->send_list.back();
if (last.iov_base+last.iov_len == cl->ssl_out_buf+cl->ssl_out_buf_size)
{
last.iov_len += n;
cl->ssl_out_buf_size += n;
return;
}
}
cl->send_list.push_back((iovec){ .iov_base = cl->ssl_out_buf+cl->ssl_out_buf_size, .iov_len = n });
cl->ssl_out_buf_size += n;
}
void reset() void reset()
{ {
op_enc = 0;
from = cl->write_op_pos; from = cl->write_op_pos;
enc_size = 0;
done_enc = 0;
if (cl->gcm_enabled) if (cl->gcm_enabled)
{ {
gcm_op_writer_t::init_ctx(msgr, cl); gcm_op_writer_t::init_ctx(msgr, cl);
} }
} }
void extend_tmp(size_t n)
{
if (!enc_buf || done_enc + n > enc_size)
{
enc_size = n < GCM_TMP_BUF_SIZE ? GCM_TMP_BUF_SIZE : n;
enc_buf = (uint8_t*)malloc_or_die(enc_size);
done_enc = 0;
assert(!((size_t)enc_buf & 7));
cl->send_free_ops.push_back((osd_op_t*)((size_t)enc_buf | 1));
}
}
void send_tmp(size_t n)
{
if (cl->send_list.size() && cl->send_list.back().iov_base == (enc_buf + done_enc))
cl->send_list.back().iov_len += n;
else
cl->send_list.push_back((iovec){ .iov_base = enc_buf + done_enc, .iov_len = n });
done += n;
done_enc += n;
}
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)
@@ -362,63 +347,54 @@ public:
from -= src_len; from -= src_len;
return true; return true;
} }
if (cl->send_list.size() >= IOV_MAX) if (cl->send_list.size() >= IOV_MAX-1)
{ {
// Make sure tag always fits
return false; return false;
} }
if (flags & WR_GCM)
{
if (cl->gcm_enabled)
{
// Encrypt data to client's temporary output buffer (all at once)
size_t n = src_len-from;
ssl_extend_buf(cl, n);
#ifdef WITH_ISAL_CRYPTO
int r = isal_aes_gcm_enc_256_update(&cl->my_key_isal, cl->enc_ctx, cl->ssl_out_buf+cl->ssl_out_buf_size, src+from, n);
assert(!r);
#else
int actual_out;
if (EVP_EncryptUpdate(cl->enc_ctx, cl->ssl_out_buf+cl->ssl_out_buf_size, &actual_out, src+from, n) != 1)
{
fprintf(stderr, "EncryptUpdate error: ");
ERR_print_errors_fp(stderr);
abort();
}
assert(actual_out == n);
#endif
if (cl->write_csum_state && !(flags & WR_NO_CSUM))
XXH3_64bits_update(cl->write_csum_state, src+from, n);
send_out_buf(cl, n);
done += n;
cl->write_op_pos += n;
from += n;
if (from < src_len)
return false;
from = 0;
return true;
}
}
if (flags & WR_XTS) if (flags & WR_XTS)
{ {
if (!cl->write_op->enc_buf) // Allocate a temporary buffer and encrypt data to it
if (!op_enc)
{ {
if (cl->send_list.size() >= IOV_MAX-1)
{
// Make sure that 1 encrypted buffer and 1 checksum fits
return false;
}
// No way except than to allocate a temporary buffer and encrypt data to it
assert(cl->write_op->req.hdr.opcode == OSD_OP_WRITE); assert(cl->write_op->req.hdr.opcode == OSD_OP_WRITE);
enc_size = cl->write_op->req.rw.len - from + (from % 16); op_enc = cl->write_op->req.rw.len - from + (from % 16);
assert(enc_size > 0); assert(op_enc > 0);
cl->write_op->enc_buf = (uint8_t*)malloc_or_die(enc_size); extend_tmp(op_enc);
cl->send_list.push_back((iovec){ .iov_base = cl->write_op->enc_buf, .iov_len = enc_size });
done += enc_size;
} }
assert(enc_size > 0); size_t new_done = done_enc;
msgr->op_encrypted_copy_buf(cl, cl->write_op->enc_buf, enc_size, src, src_len, from, done_enc); msgr->op_encrypted_copy_buf(cl, enc_buf, enc_size, src, src_len, from, new_done);
send_tmp(new_done-done_enc);
assert(from == src_len); assert(from == src_len);
} }
else if ((flags & WR_GCM) && cl->gcm_enabled)
{
// Allocate a temporary buffer and encrypt data to it
size_t n = src_len-from;
extend_tmp(n);
#ifdef WITH_ISAL_CRYPTO
int r = isal_aes_gcm_enc_256_update(&cl->my_key_isal, cl->enc_ctx, enc_buf+done_enc, src+from, n);
assert(!r);
#else
int actual_out;
if (EVP_EncryptUpdate(cl->enc_ctx, enc_buf+done_enc, &actual_out, src+from, n) != 1)
{
fprintf(stderr, "EncryptUpdate error: ");
ERR_print_errors_fp(stderr);
abort();
}
assert(actual_out == n);
#endif
if (cl->write_csum_state && !(flags & WR_NO_CSUM))
XXH3_64bits_update(cl->write_csum_state, src+from, n);
send_tmp(n);
cl->write_op_pos += n;
from += n;
if (from < src_len)
return false;
from = 0;
return true;
}
else else
{ {
if (cl->write_csum_state && !(flags & WR_NO_CSUM)) if (cl->write_csum_state && !(flags & WR_NO_CSUM))
@@ -435,13 +411,10 @@ public:
{ {
if (cl->enc_ctx) if (cl->enc_ctx)
{ {
if (cl->send_list.size() >= IOV_MAX)
return false;
// Tag is 16 bytes // Tag is 16 bytes
ssl_extend_buf(cl, 16); extend_tmp(16);
gcm_op_writer_t::write_tag_to(msgr, cl, cl->ssl_out_buf+cl->ssl_out_buf_size); gcm_op_writer_t::write_tag_to(msgr, cl, enc_buf + done_enc);
send_out_buf(cl, 16); send_tmp(16);
done += 16;
gcm_op_writer_t::free_ctx(msgr, cl); gcm_op_writer_t::free_ctx(msgr, cl);
} }
return true; return true;
@@ -527,14 +500,15 @@ bool osd_messenger_t::try_send(osd_client_t *cl)
if (cl->hs) if (cl->hs)
{ {
// Send handshake message // Send handshake message
if (cl->hs->get_out().size()) if (cl->hs->out_size())
{ {
get_op_writer_t::ssl_extend_buf(cl, cl->hs->get_out().size()); uint8_t *out = cl->hs->get_out();
memcpy(cl->ssl_out_buf+cl->ssl_out_buf_size, cl->hs->get_out().data(), cl->hs->get_out().size()); cl->send_list.push_back((iovec){ .iov_base = out, .iov_len = cl->hs->out_size() });
get_op_writer_t::send_out_buf(cl, cl->hs->get_out().size()); assert(!((size_t)out & 7));
cl->hs->get_out().clear(); cl->send_free_ops.push_back((osd_op_t*)((size_t)out | 1));
cl->hs->reset_out();
} }
if (!cl->hs->get_out().size() && cl->hs->done()) if (!cl->hs->out_size() && cl->hs->done())
{ {
delete cl->hs; delete cl->hs;
cl->hs = NULL; cl->hs = NULL;
@@ -621,13 +595,13 @@ size_t osd_messenger_t::copy_ops_to(osd_client_t *cl, uint8_t *dst, size_t dst_l
{ {
// Send handshake message // Send handshake message
size_t n = 0; size_t n = 0;
if (cl->hs->get_out().size()) if (cl->hs->out_size())
{ {
n = cl->hs->get_out().size() < dst_len ? cl->hs->get_out().size() : dst_len; n = cl->hs->out_size() < dst_len ? cl->hs->out_size() : dst_len;
memcpy(dst, cl->hs->get_out().data(), n); memcpy(dst, cl->hs->get_out(), n);
cl->hs->get_out().erase(cl->hs->get_out().begin(), cl->hs->get_out().begin() + n); cl->hs->eat_out(n);
} }
if (!cl->hs->get_out().size() && cl->hs->done()) if (!cl->hs->out_size() && cl->hs->done())
{ {
delete cl->hs; delete cl->hs;
cl->hs = NULL; cl->hs = NULL;
@@ -750,24 +724,14 @@ void osd_messenger_t::handle_send(int result, bool prev, bool more, osd_client_t
for (auto op: cl->send_free_ops) for (auto op: cl->send_free_ops)
{ {
if (more) if (more)
{
assert(!((size_t)op & 7));
cl->zc_free_list.push_back(op); cl->zc_free_list.push_back(op);
} else if (!((size_t)op & 7))
else
delete op; delete op;
else
free((void*)((size_t)op & ~(size_t)7));
} }
if (more) if (more)
{
if (cl->ssl_out_buf_size)
{
cl->zc_free_list.push_back((osd_op_t*)((size_t)cl->ssl_out_buf | 1));
cl->ssl_out_buf = NULL;
cl->ssl_out_buf_cap = 0;
}
cl->zc_free_list.push_back(NULL); // end marker cl->zc_free_list.push_back(NULL); // end marker
}
cl->ssl_out_buf_size = 0;
cl->send_free_ops.clear(); cl->send_free_ops.clear();
cl->write_state = 0; cl->write_state = 0;
if (cl->write_op || cl->write_ops.size()) if (cl->write_op || cl->write_ops.size())
@@ -875,7 +839,7 @@ bool osd_messenger_t::op_write_to(osd_client_t *cl, msgr_op_writer_t & wr)
for (int i = 0; i < cl->write_op->iov.count; i++) for (int i = 0; i < cl->write_op->iov.count; i++)
{ {
auto & iov = cl->write_op->iov.buf[i]; auto & iov = cl->write_op->iov.buf[i];
if (!wr.write((uint8_t*)iov.iov_base, iov.iov_len, (op->enc ? WR_XTS : 0))) if (!wr.write((uint8_t*)iov.iov_base, iov.iov_len, (op->enc ? WR_XTS : 0) | (cl->proto_csum_status == MSGR_CSUM_GCM ? WR_GCM : 0)))
return false; return false;
} }
} }
+4 -6
View File
@@ -202,7 +202,10 @@ osd_client_t::~osd_client_t()
{ {
if (op) if (op)
{ {
delete op; if (!((size_t)op & 7))
delete op;
else
free((void*)((size_t)op & ~(size_t)7));
} }
} }
for (osd_op_t *op: zc_free_list) for (osd_op_t *op: zc_free_list)
@@ -243,11 +246,6 @@ osd_client_t::~osd_client_t()
#endif #endif
dec_ctx = NULL; dec_ctx = NULL;
} }
if (ssl_out_buf)
{
free(ssl_out_buf);
ssl_out_buf = NULL;
}
if (hs) if (hs)
{ {
delete hs; delete hs;
+11 -2
View File
@@ -376,14 +376,23 @@ void osd_t::exec_show_config(osd_op_t *cur_op)
if (msgr.use_proto_checksums) if (msgr.use_proto_checksums)
{ {
auto peer_csums = req_json["features"]["proto_checksums"].uint64_value(); auto peer_csums = req_json["features"]["proto_checksums"].uint64_value();
if (peer_csums == MSGR_CSUM_FULL || peer_csums == MSGR_CSUM_PAYLOAD) if (peer_csums == MSGR_CSUM_FULL || peer_csums == MSGR_CSUM_PAYLOAD ||
cl->gcm_enabled && peer_csums == MSGR_CSUM_GCM)
{ {
if (msgr.use_proto_checksums == MSGR_CSUM_FULL && peer_csums == MSGR_CSUM_FULL) if (msgr.use_proto_checksums == MSGR_CSUM_GCM && peer_csums == MSGR_CSUM_GCM)
cl->proto_csum_status = MSGR_CSUM_GCM|MSGR_CSUM_NEG;
else if (msgr.use_proto_checksums == MSGR_CSUM_FULL && peer_csums == MSGR_CSUM_FULL)
cl->proto_csum_status = MSGR_CSUM_FULL|MSGR_CSUM_NEG; cl->proto_csum_status = MSGR_CSUM_FULL|MSGR_CSUM_NEG;
else else
cl->proto_csum_status = MSGR_CSUM_PAYLOAD|MSGR_CSUM_NEG; cl->proto_csum_status = MSGR_CSUM_PAYLOAD|MSGR_CSUM_NEG;
features["proto_checksums"] = msgr.use_proto_checksums; features["proto_checksums"] = msgr.use_proto_checksums;
} }
if (peer_csums < msgr.force_proto_checksums)
{
fprintf(stderr, "Error: Client %ju use_proto_checksums security level is lower than force_proto_checksums\n", cl->client_id);
msgr.stop_client(cl->client_id);
return;
}
} }
// Expose sensitive configuration values so peers can check them // Expose sensitive configuration values so peers can check them
json11::Json::object wire_config = json11::Json::object { json11::Json::object wire_config = json11::Json::object {
+12 -10
View File
@@ -663,11 +663,12 @@ void test_msgr_encrypt()
uint8_t *crypt2 = (uint8_t*)malloc_or_die(sz); uint8_t *crypt2 = (uint8_t*)malloc_or_die(sz);
uint8_t *key = (uint8_t*)malloc_or_die(64); uint8_t *key = (uint8_t*)malloc_or_die(64);
RAND_bytes(key, 64); RAND_bytes(key, 64);
osd_client_t cl;
// Basic encrypt+decrypt and also get reference data // Basic encrypt+decrypt and also get reference data
auto enc = new op_aes_xts_encrypt_t(); auto enc = new op_aes_xts_encrypt_t();
enc->start(key, 4096 * 113, 4096); enc->start(&cl, key, 4096 * 113, 4096);
size_t in_pos = 0; size_t in_pos = 0;
size_t out_pos = 0; size_t out_pos = 0;
while (out_pos < sz) while (out_pos < sz)
@@ -676,7 +677,7 @@ void test_msgr_encrypt()
} }
auto dec = new op_aes_xts_decrypt_t(); auto dec = new op_aes_xts_decrypt_t();
dec->start(&key, 1, NULL, 4096 * 113, 4096); dec->start(&cl, &key, 1, NULL, 4096 * 113, 4096);
in_pos = out_pos = 0; in_pos = out_pos = 0;
while (out_pos < sz) while (out_pos < sz)
{ {
@@ -687,7 +688,7 @@ void test_msgr_encrypt()
// Insufficient output encrypt // Insufficient output encrypt
printf("...insufficient output encrypt\n"); printf("...insufficient output encrypt\n");
enc->start(key, 4096 * 114, 4096); enc->start(&cl, key, 4096 * 114, 4096);
in_pos = out_pos = 0; in_pos = out_pos = 0;
enc->update(src+4096, 4096, crypt2, 4095, in_pos, out_pos); enc->update(src+4096, 4096, crypt2, 4095, in_pos, out_pos);
assert(in_pos == 4095); assert(in_pos == 4095);
@@ -699,7 +700,7 @@ void test_msgr_encrypt()
// Fragmented encrypt // Fragmented encrypt
printf("...fragmented encrypt\n"); printf("...fragmented encrypt\n");
enc->start(key, 4096 * 114, 4096); enc->start(&cl, key, 4096 * 114, 4096);
in_pos = out_pos = 0; in_pos = out_pos = 0;
enc->update(src+4096, 2000, crypt2, 4095, in_pos, out_pos); enc->update(src+4096, 2000, crypt2, 4095, in_pos, out_pos);
assert(in_pos == 2000); assert(in_pos == 2000);
@@ -712,7 +713,7 @@ void test_msgr_encrypt()
// Fragmented decrypt // Fragmented decrypt
// Input: 1000 + 2000 + 3000 + 2192, output: 500 + 3000 + 1000 + 3000 + 692 // Input: 1000 + 2000 + 3000 + 2192, output: 500 + 3000 + 1000 + 3000 + 692
printf("...fragmented decrypt\n"); printf("...fragmented decrypt\n");
dec->start(&key, 1, NULL, 4096 * 114, 4096); dec->start(&cl, &key, 1, NULL, 4096 * 114, 4096);
in_pos = out_pos = 0; in_pos = out_pos = 0;
dec->update(crypt+4096, 1000, decrypt, 500, in_pos, out_pos); dec->update(crypt+4096, 1000, decrypt, 500, in_pos, out_pos);
assert(in_pos == 1000); assert(in_pos == 1000);
@@ -746,7 +747,7 @@ void test_msgr_encrypt()
// Extra size decrypt // Extra size decrypt
// Input: 8192, output: 4096 // Input: 8192, output: 4096
printf("...extra size decrypt\n"); printf("...extra size decrypt\n");
dec->start(&key, 1, NULL, 4096 * 114, 4096); dec->start(&cl, &key, 1, NULL, 4096 * 114, 4096);
in_pos = out_pos = 0; in_pos = out_pos = 0;
dec->update(crypt+4096, 8192, decrypt, 4096, in_pos, out_pos); dec->update(crypt+4096, 8192, decrypt, 4096, in_pos, out_pos);
assert(in_pos == 4096); assert(in_pos == 4096);
@@ -776,6 +777,7 @@ void test_msgr_decrypt_chain()
RAND_bytes(key, 64); RAND_bytes(key, 64);
uint8_t *key2 = (uint8_t*)malloc_or_die(64); uint8_t *key2 = (uint8_t*)malloc_or_die(64);
RAND_bytes(key2, 64); RAND_bytes(key2, 64);
osd_client_t cl;
// Chained decryption with multiple keys // Chained decryption with multiple keys
@@ -783,17 +785,17 @@ void test_msgr_decrypt_chain()
size_t in_pos = 0, out_pos = 0; size_t in_pos = 0, out_pos = 0;
auto enc = new op_aes_xts_encrypt_t(); auto enc = new op_aes_xts_encrypt_t();
// block 1 with key1 // block 1 with key1
enc->start(key, 4096 * 113, 4096); enc->start(&cl, key, 4096 * 113, 4096);
enc->update(src, 4096, crypt, 4096, in_pos, out_pos); enc->update(src, 4096, crypt, 4096, in_pos, out_pos);
assert(in_pos == 4096 && out_pos == 4096); assert(in_pos == 4096 && out_pos == 4096);
// block 2 as plain // block 2 as plain
memcpy(crypt + 4096, src + 4096, 4096); memcpy(crypt + 4096, src + 4096, 4096);
// block 3 with key2 // block 3 with key2
enc->start(key2, 4096 * 115, 4096); enc->start(&cl, key2, 4096 * 115, 4096);
enc->update(src + 2*4096, 4096, crypt + 2*4096, 4096, in_pos, out_pos); enc->update(src + 2*4096, 4096, crypt + 2*4096, 4096, in_pos, out_pos);
assert(in_pos == 2*4096 && out_pos == 2*4096); assert(in_pos == 2*4096 && out_pos == 2*4096);
// block 4 again with key1 // block 4 again with key1
enc->start(key, 4096 * 116, 4096); enc->start(&cl, key, 4096 * 116, 4096);
enc->update(src + 3*4096, 4096, crypt + 3*4096, 4096, in_pos, out_pos); enc->update(src + 3*4096, 4096, crypt + 3*4096, 4096, in_pos, out_pos);
assert(in_pos == 3*4096 && out_pos == 3*4096); assert(in_pos == 3*4096 && out_pos == 3*4096);
@@ -801,7 +803,7 @@ void test_msgr_decrypt_chain()
uint8_t* keys[3] = { key, key2, NULL }; uint8_t* keys[3] = { key, key2, NULL };
uint8_t chain_info[4] = { 0, 2, 1, 0 }; uint8_t chain_info[4] = { 0, 2, 1, 0 };
auto dec = new op_aes_xts_decrypt_t(); auto dec = new op_aes_xts_decrypt_t();
dec->start(keys, 3, chain_info, 4096 * 113, 4096); dec->start(&cl, keys, 3, chain_info, 4096 * 113, 4096);
in_pos = out_pos = 0; in_pos = out_pos = 0;
while (out_pos < sz) while (out_pos < sz)
{ {
+1
View File
@@ -63,6 +63,7 @@ OLD=1 ./test_move_reappear.sh
./test_snapshot_chain.sh ./test_snapshot_chain.sh
SCHEME=ec ./test_snapshot_chain.sh SCHEME=ec ./test_snapshot_chain.sh
ENCRYPTED=1 ./test_snapshot_chain.sh ENCRYPTED=1 ./test_snapshot_chain.sh
TEST_NAME=enc_gcm ENCRYPTED=1 VITASTOR_CFG=',"proto_checksums":"gcm"' ./test_snapshot_chain.sh
OLD=1 ./test_snapshot_chain.sh OLD=1 ./test_snapshot_chain.sh
OLD=1 SCHEME=ec ./test_snapshot_chain.sh OLD=1 SCHEME=ec ./test_snapshot_chain.sh