Add support for full AES-GCM including double encryption of AES-XTS :D
This commit is contained in:
@@ -792,6 +792,24 @@ jobs:
|
||||
echo ""
|
||||
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:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
|
||||
+40
-16
@@ -197,19 +197,34 @@ osd_messenger_t::~osd_messenger_t()
|
||||
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)
|
||||
{
|
||||
this->max_cipher_pool_size = config["max_cipher_pool_size"].uint64_value();
|
||||
if (!this->max_cipher_pool_size)
|
||||
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();
|
||||
if (!this->receive_buffer_size || this->receive_buffer_size > 1024*1024*1024)
|
||||
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();
|
||||
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)
|
||||
this->iothread_count = (uint32_t)config["client_iothread_count"].uint64_value();
|
||||
else
|
||||
@@ -653,6 +670,21 @@ void osd_messenger_t::check_peer_config(osd_client_t *cl)
|
||||
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)
|
||||
{
|
||||
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;
|
||||
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
|
||||
if (!use_rdmacm && cl->rdma_conn && config["rdma_address"].is_string())
|
||||
{
|
||||
|
||||
@@ -41,7 +41,8 @@
|
||||
|
||||
#define MSGR_CSUM_PAYLOAD 1
|
||||
#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"
|
||||
|
||||
@@ -92,9 +93,6 @@ struct osd_client_t
|
||||
msgr_rdma_connection_t *rdma_conn = NULL;
|
||||
#endif
|
||||
|
||||
uint8_t *ssl_out_buf = NULL;
|
||||
size_t ssl_out_buf_size = 0, ssl_out_buf_cap = 0;
|
||||
|
||||
bool gcm_enabled = false;
|
||||
msgr_handshake_i *hs = NULL;
|
||||
msgr_handshake_result_t hs_result;
|
||||
@@ -290,6 +288,7 @@ public:
|
||||
std::vector<std::string> all_osd_networks;
|
||||
std::vector<addr_mask_t> all_osd_network_masks;
|
||||
int use_proto_checksums = 0;
|
||||
int force_proto_checksums = 0;
|
||||
// op statistics
|
||||
osd_op_stats_t stats, recovery_stats;
|
||||
|
||||
|
||||
@@ -44,9 +44,10 @@ op_aes_xts_encrypt_t::~op_aes_xts_encrypt_t()
|
||||
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);
|
||||
this->cl = cl;
|
||||
this->start_offset = start_offset;
|
||||
this->key = key;
|
||||
this->block_size = block_size;
|
||||
@@ -91,6 +92,28 @@ void op_aes_xts_encrypt_t::encrypt_block(uint8_t *in, uint8_t *out)
|
||||
#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)
|
||||
{
|
||||
// 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);
|
||||
if (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;
|
||||
tmp_pos += max_out;
|
||||
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);
|
||||
encrypt_block(tmp, tmp);
|
||||
encrypted = true;
|
||||
memcpy(out, tmp, max_out);
|
||||
copy_or_gcm(cl, out, tmp, max_out);
|
||||
tmp_pos = max_out;
|
||||
done_in += max_in-1;
|
||||
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
|
||||
encrypt_block(in, out);
|
||||
if (cl->proto_csum_status == MSGR_CSUM_GCM)
|
||||
copy_or_gcm(cl, out, out, block_size);
|
||||
done_in += block_size;
|
||||
offset += 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;
|
||||
memcpy(tmp + offset%block_size, in, max_in);
|
||||
encrypt_block(tmp, out);
|
||||
if (cl->proto_csum_status == MSGR_CSUM_GCM)
|
||||
copy_or_gcm(cl, out, out, block_size);
|
||||
done_in += max_in;
|
||||
offset += max_in;
|
||||
done_out += block_size;
|
||||
@@ -196,9 +223,10 @@ op_aes_xts_decrypt_t::~op_aes_xts_decrypt_t()
|
||||
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);
|
||||
this->cl = cl;
|
||||
this->start_offset = start_offset;
|
||||
this->key_chain = key_chain;
|
||||
this->chain_size = chain_size;
|
||||
@@ -269,6 +297,23 @@ void op_aes_xts_decrypt_t::decrypt_block(uint8_t *in, uint8_t *out)
|
||||
#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,
|
||||
// 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)
|
||||
@@ -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;
|
||||
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);
|
||||
decrypted = true;
|
||||
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))
|
||||
{
|
||||
// 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);
|
||||
done_in += 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;
|
||||
memcpy(tmp + offset%block_size, in, max_in);
|
||||
assert(out);
|
||||
if (cl->proto_csum_status == MSGR_CSUM_GCM)
|
||||
gcm_dec(cl, tmp, tmp, block_size);
|
||||
decrypt_block(tmp, out);
|
||||
done_in += 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
|
||||
cl->xts_enc_ctx = new op_aes_xts_encrypt_t();
|
||||
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)
|
||||
{
|
||||
@@ -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();
|
||||
auto & enc = cl->read_op->enc;
|
||||
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.offset, enc->bitmap_granularity);
|
||||
}
|
||||
@@ -561,7 +621,7 @@ void osd_messenger_t::init_tls_client(osd_client_t *cl)
|
||||
cl->gcm_enabled = true;
|
||||
cl->hs = hs_ctx->create();
|
||||
cl->hs->init(cl->is_incoming);
|
||||
if (cl->hs->get_out().size())
|
||||
if (cl->hs->out_size())
|
||||
{
|
||||
if (cl->write_state == 0)
|
||||
{
|
||||
|
||||
@@ -12,11 +12,14 @@
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
struct osd_client_t;
|
||||
|
||||
class op_aes_xts_encrypt_t
|
||||
{
|
||||
#ifndef WITH_ISAL_CRYPTO
|
||||
EVP_CIPHER_CTX *ctx = NULL;
|
||||
#endif
|
||||
osd_client_t *cl = NULL;
|
||||
uint64_t start_offset = 0;
|
||||
uint8_t *key = NULL;
|
||||
size_t offset = 0;
|
||||
@@ -32,7 +35,7 @@ public:
|
||||
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);
|
||||
};
|
||||
|
||||
@@ -43,6 +46,7 @@ class op_aes_xts_decrypt_t
|
||||
#ifndef WITH_ISAL_CRYPTO
|
||||
EVP_CIPHER_CTX *ctx = NULL;
|
||||
#endif
|
||||
osd_client_t *cl = NULL;
|
||||
uint64_t start_offset = 0;
|
||||
uint8_t **key_chain = NULL;
|
||||
size_t chain_size = 0;
|
||||
@@ -61,7 +65,7 @@ public:
|
||||
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);
|
||||
};
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "msgr_handshake.h"
|
||||
#include "malloc_or_die.h"
|
||||
#include "openssl_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> in_buf;
|
||||
std::vector<uint8_t> out_buf;
|
||||
uint8_t *out_buf = NULL;
|
||||
size_t out_buf_size = 0;
|
||||
std::string error;
|
||||
|
||||
int state = 0;
|
||||
@@ -125,7 +127,10 @@ public:
|
||||
bool init(bool server_mode) override;
|
||||
ssize_t handle(uint8_t* in_buf, size_t in_size) 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;
|
||||
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()
|
||||
{
|
||||
if (out_buf)
|
||||
free(out_buf);
|
||||
if (peer_cert)
|
||||
X509_free(peer_cert);
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
if (!key_len)
|
||||
return on_error("EVP_PKEY_get1_encoded_public_key: ");
|
||||
const size_t old_len = out_buf.size();
|
||||
out_buf.resize(out_buf.size() + key_len + sizeof(msgr_handshake_hdr_t));
|
||||
uint8_t *buf = out_buf.data() + old_len;
|
||||
const size_t old_out_size = out_buf_size;
|
||||
out_buf_size += key_len + sizeof(msgr_handshake_hdr_t);
|
||||
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;
|
||||
hdr->msg_len = key_len + sizeof(msgr_handshake_hdr_t);
|
||||
hdr->magic = MSGR_HS_MAGIC;
|
||||
@@ -485,9 +499,12 @@ bool msgr_handshake_t::make_server_reply()
|
||||
}
|
||||
// Construct message
|
||||
hdr.msg_len = sizeof(msgr_handshake_hdr_t) + 4 + key_len + encrypt_data.size();
|
||||
copy_to(out_buf, &hdr, sizeof(hdr));
|
||||
copy_to_with_len(out_buf, key, key_len);
|
||||
copy_to(out_buf, encrypt_data.data(), encrypt_data.size());
|
||||
out_buf = (uint8_t*)realloc_or_die(out_buf, (out_buf_size += hdr.msg_len));
|
||||
uint8_t *cur = out_buf + out_buf_size - hdr.msg_len;
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
@@ -510,8 +527,10 @@ bool msgr_handshake_t::make_client_reply()
|
||||
return false;
|
||||
// Construct message
|
||||
hdr.msg_len = sizeof(msgr_handshake_hdr_t) + encrypt_data.size();
|
||||
copy_to(out_buf, &hdr, sizeof(hdr));
|
||||
copy_to(out_buf, encrypt_data.data(), encrypt_data.size());
|
||||
out_buf = (uint8_t*)realloc_or_die(out_buf, (out_buf_size += hdr.msg_len));
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -742,11 +761,37 @@ bool msgr_handshake_t::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;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
if (state != MSGR_HS_DONE)
|
||||
|
||||
@@ -35,7 +35,10 @@ public:
|
||||
virtual bool init(bool server_mode) = 0;
|
||||
virtual ssize_t handle(uint8_t* in_buf, size_t in_size) = 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 std::string get_error() = 0;
|
||||
};
|
||||
|
||||
@@ -24,10 +24,6 @@ osd_op_t::~osd_op_t()
|
||||
// So we don't reuse it, but free it every time
|
||||
free(buf);
|
||||
}
|
||||
if (enc_buf)
|
||||
{
|
||||
free(enc_buf);
|
||||
}
|
||||
}
|
||||
|
||||
bool osd_op_t::is_recovery_related()
|
||||
|
||||
@@ -186,7 +186,6 @@ struct __attribute__((visibility("default"))) osd_op_t
|
||||
uint8_t *bitmap_buf = NULL;
|
||||
void *rmw_buf = NULL;
|
||||
std::shared_ptr<osd_op_enc_t> enc;
|
||||
uint8_t *enc_buf = NULL;
|
||||
uint64_t csum = 0; // network layer checksum
|
||||
osd_primary_op_data_t* op_data = NULL;
|
||||
std::function<void(osd_op_t*)> callback;
|
||||
|
||||
@@ -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)
|
||||
rc->send_done_pos = 0;
|
||||
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();
|
||||
|
||||
+28
-40
@@ -170,41 +170,17 @@ public:
|
||||
if (done >= bufsize)
|
||||
return false;
|
||||
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)
|
||||
n = bufsize-done;
|
||||
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;
|
||||
}
|
||||
msgr->op_decrypted_copy_buf(cl, curbuf, bufsize, dst, dst_len, from, done);
|
||||
n = 0;
|
||||
}
|
||||
else
|
||||
else if (flags & RDR_GCM)
|
||||
{
|
||||
// Here, dst == NULL is not allowed
|
||||
assert(dst != NULL);
|
||||
size_t n = dst_len-from;
|
||||
if (n > bufsize-done)
|
||||
n = bufsize-done;
|
||||
#ifdef WITH_ISAL_CRYPTO
|
||||
int r = isal_aes_gcm_dec_256_update(&cl->peer_key_isal, cl->dec_ctx, dst+from, curbuf+done, n);
|
||||
assert(!r);
|
||||
@@ -223,12 +199,24 @@ public:
|
||||
XXH3_64bits_update(cl->read_csum_state, dst+from, n);
|
||||
}
|
||||
done += n;
|
||||
from += n;
|
||||
cl->read_op_pos += n;
|
||||
if (from < dst_len)
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
return true;
|
||||
@@ -605,7 +593,7 @@ bool osd_messenger_t::handle_read_buffer(osd_client_t *cl, uint8_t *curbuf, size
|
||||
}
|
||||
curbuf += done;
|
||||
bufsize -= done;
|
||||
if (cl->hs->get_out().size())
|
||||
if (cl->hs->out_size())
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
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 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))
|
||||
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;
|
||||
}
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
else if (op->req.hdr.opcode == OSD_OP_SHOW_CONFIG)
|
||||
@@ -973,7 +961,7 @@ switched_type:
|
||||
if (op->reply.hdr.retval > 0)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -987,7 +975,7 @@ switched_type:
|
||||
if (op->reply.hdr.retval > 0)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
+102
-138
@@ -15,6 +15,8 @@
|
||||
#define WR_XTS 2
|
||||
#define WR_NO_CSUM 4
|
||||
|
||||
#define GCM_TMP_BUF_SIZE 4096
|
||||
|
||||
class msgr_op_writer_t
|
||||
{
|
||||
public:
|
||||
@@ -180,28 +182,11 @@ public:
|
||||
from -= src_len;
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
msgr->op_encrypted_copy_buf(cl, curbuf, bufsize, src, src_len, from, done);
|
||||
}
|
||||
else
|
||||
else if (flags & WR_GCM)
|
||||
{
|
||||
size_t n = src_len-from;
|
||||
if (n > bufsize-done)
|
||||
@@ -227,6 +212,20 @@ public:
|
||||
cl->write_op_pos += 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)
|
||||
return false;
|
||||
from = 0;
|
||||
@@ -297,63 +296,49 @@ class get_op_writer_t: public msgr_op_writer_t
|
||||
osd_client_t* cl;
|
||||
size_t from;
|
||||
size_t done;
|
||||
size_t op_enc;
|
||||
size_t enc_size;
|
||||
size_t done_enc;
|
||||
uint8_t *enc_buf;
|
||||
|
||||
public:
|
||||
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()
|
||||
{
|
||||
op_enc = 0;
|
||||
from = cl->write_op_pos;
|
||||
enc_size = 0;
|
||||
done_enc = 0;
|
||||
if (cl->gcm_enabled)
|
||||
{
|
||||
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
|
||||
{
|
||||
if (from >= src_len)
|
||||
@@ -362,63 +347,54 @@ public:
|
||||
from -= src_len;
|
||||
return true;
|
||||
}
|
||||
if (cl->send_list.size() >= IOV_MAX)
|
||||
if (cl->send_list.size() >= IOV_MAX-1)
|
||||
{
|
||||
// Make sure tag always fits
|
||||
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 (!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);
|
||||
enc_size = cl->write_op->req.rw.len - from + (from % 16);
|
||||
assert(enc_size > 0);
|
||||
cl->write_op->enc_buf = (uint8_t*)malloc_or_die(enc_size);
|
||||
cl->send_list.push_back((iovec){ .iov_base = cl->write_op->enc_buf, .iov_len = enc_size });
|
||||
done += enc_size;
|
||||
op_enc = cl->write_op->req.rw.len - from + (from % 16);
|
||||
assert(op_enc > 0);
|
||||
extend_tmp(op_enc);
|
||||
}
|
||||
assert(enc_size > 0);
|
||||
msgr->op_encrypted_copy_buf(cl, cl->write_op->enc_buf, enc_size, src, src_len, from, done_enc);
|
||||
size_t new_done = 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);
|
||||
}
|
||||
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
|
||||
{
|
||||
if (cl->write_csum_state && !(flags & WR_NO_CSUM))
|
||||
@@ -435,13 +411,10 @@ public:
|
||||
{
|
||||
if (cl->enc_ctx)
|
||||
{
|
||||
if (cl->send_list.size() >= IOV_MAX)
|
||||
return false;
|
||||
// Tag is 16 bytes
|
||||
ssl_extend_buf(cl, 16);
|
||||
gcm_op_writer_t::write_tag_to(msgr, cl, cl->ssl_out_buf+cl->ssl_out_buf_size);
|
||||
send_out_buf(cl, 16);
|
||||
done += 16;
|
||||
extend_tmp(16);
|
||||
gcm_op_writer_t::write_tag_to(msgr, cl, enc_buf + done_enc);
|
||||
send_tmp(16);
|
||||
gcm_op_writer_t::free_ctx(msgr, cl);
|
||||
}
|
||||
return true;
|
||||
@@ -527,14 +500,15 @@ bool osd_messenger_t::try_send(osd_client_t *cl)
|
||||
if (cl->hs)
|
||||
{
|
||||
// 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());
|
||||
memcpy(cl->ssl_out_buf+cl->ssl_out_buf_size, cl->hs->get_out().data(), cl->hs->get_out().size());
|
||||
get_op_writer_t::send_out_buf(cl, cl->hs->get_out().size());
|
||||
cl->hs->get_out().clear();
|
||||
uint8_t *out = cl->hs->get_out();
|
||||
cl->send_list.push_back((iovec){ .iov_base = out, .iov_len = cl->hs->out_size() });
|
||||
assert(!((size_t)out & 7));
|
||||
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;
|
||||
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
|
||||
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;
|
||||
memcpy(dst, cl->hs->get_out().data(), n);
|
||||
cl->hs->get_out().erase(cl->hs->get_out().begin(), cl->hs->get_out().begin() + n);
|
||||
n = cl->hs->out_size() < dst_len ? cl->hs->out_size() : dst_len;
|
||||
memcpy(dst, cl->hs->get_out(), 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;
|
||||
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)
|
||||
{
|
||||
if (more)
|
||||
{
|
||||
assert(!((size_t)op & 7));
|
||||
cl->zc_free_list.push_back(op);
|
||||
}
|
||||
else
|
||||
else if (!((size_t)op & 7))
|
||||
delete op;
|
||||
else
|
||||
free((void*)((size_t)op & ~(size_t)7));
|
||||
}
|
||||
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->ssl_out_buf_size = 0;
|
||||
cl->send_free_ops.clear();
|
||||
cl->write_state = 0;
|
||||
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++)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,7 +202,10 @@ osd_client_t::~osd_client_t()
|
||||
{
|
||||
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)
|
||||
@@ -243,11 +246,6 @@ osd_client_t::~osd_client_t()
|
||||
#endif
|
||||
dec_ctx = NULL;
|
||||
}
|
||||
if (ssl_out_buf)
|
||||
{
|
||||
free(ssl_out_buf);
|
||||
ssl_out_buf = NULL;
|
||||
}
|
||||
if (hs)
|
||||
{
|
||||
delete hs;
|
||||
|
||||
@@ -376,14 +376,23 @@ void osd_t::exec_show_config(osd_op_t *cur_op)
|
||||
if (msgr.use_proto_checksums)
|
||||
{
|
||||
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;
|
||||
else
|
||||
cl->proto_csum_status = MSGR_CSUM_PAYLOAD|MSGR_CSUM_NEG;
|
||||
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
|
||||
json11::Json::object wire_config = json11::Json::object {
|
||||
|
||||
@@ -663,11 +663,12 @@ void test_msgr_encrypt()
|
||||
uint8_t *crypt2 = (uint8_t*)malloc_or_die(sz);
|
||||
uint8_t *key = (uint8_t*)malloc_or_die(64);
|
||||
RAND_bytes(key, 64);
|
||||
osd_client_t cl;
|
||||
|
||||
// Basic encrypt+decrypt and also get reference data
|
||||
|
||||
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 out_pos = 0;
|
||||
while (out_pos < sz)
|
||||
@@ -676,7 +677,7 @@ void test_msgr_encrypt()
|
||||
}
|
||||
|
||||
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;
|
||||
while (out_pos < sz)
|
||||
{
|
||||
@@ -687,7 +688,7 @@ void test_msgr_encrypt()
|
||||
|
||||
// Insufficient output encrypt
|
||||
printf("...insufficient output encrypt\n");
|
||||
enc->start(key, 4096 * 114, 4096);
|
||||
enc->start(&cl, key, 4096 * 114, 4096);
|
||||
in_pos = out_pos = 0;
|
||||
enc->update(src+4096, 4096, crypt2, 4095, in_pos, out_pos);
|
||||
assert(in_pos == 4095);
|
||||
@@ -699,7 +700,7 @@ void test_msgr_encrypt()
|
||||
|
||||
// Fragmented encrypt
|
||||
printf("...fragmented encrypt\n");
|
||||
enc->start(key, 4096 * 114, 4096);
|
||||
enc->start(&cl, key, 4096 * 114, 4096);
|
||||
in_pos = out_pos = 0;
|
||||
enc->update(src+4096, 2000, crypt2, 4095, in_pos, out_pos);
|
||||
assert(in_pos == 2000);
|
||||
@@ -712,7 +713,7 @@ void test_msgr_encrypt()
|
||||
// Fragmented decrypt
|
||||
// Input: 1000 + 2000 + 3000 + 2192, output: 500 + 3000 + 1000 + 3000 + 692
|
||||
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;
|
||||
dec->update(crypt+4096, 1000, decrypt, 500, in_pos, out_pos);
|
||||
assert(in_pos == 1000);
|
||||
@@ -746,7 +747,7 @@ void test_msgr_encrypt()
|
||||
// Extra size decrypt
|
||||
// Input: 8192, output: 4096
|
||||
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;
|
||||
dec->update(crypt+4096, 8192, decrypt, 4096, in_pos, out_pos);
|
||||
assert(in_pos == 4096);
|
||||
@@ -776,6 +777,7 @@ void test_msgr_decrypt_chain()
|
||||
RAND_bytes(key, 64);
|
||||
uint8_t *key2 = (uint8_t*)malloc_or_die(64);
|
||||
RAND_bytes(key2, 64);
|
||||
osd_client_t cl;
|
||||
|
||||
// Chained decryption with multiple keys
|
||||
|
||||
@@ -783,17 +785,17 @@ void test_msgr_decrypt_chain()
|
||||
size_t in_pos = 0, out_pos = 0;
|
||||
auto enc = new op_aes_xts_encrypt_t();
|
||||
// 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);
|
||||
assert(in_pos == 4096 && out_pos == 4096);
|
||||
// block 2 as plain
|
||||
memcpy(crypt + 4096, src + 4096, 4096);
|
||||
// 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);
|
||||
assert(in_pos == 2*4096 && out_pos == 2*4096);
|
||||
// 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);
|
||||
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 chain_info[4] = { 0, 2, 1, 0 };
|
||||
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;
|
||||
while (out_pos < sz)
|
||||
{
|
||||
|
||||
@@ -63,6 +63,7 @@ OLD=1 ./test_move_reappear.sh
|
||||
./test_snapshot_chain.sh
|
||||
SCHEME=ec ./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 SCHEME=ec ./test_snapshot_chain.sh
|
||||
|
||||
|
||||
Reference in New Issue
Block a user