Compare commits

...
16 changed files with 391 additions and 197 deletions
+6 -8
View File
@@ -12,20 +12,18 @@ ARG REL=
WORKDIR /root WORKDIR /root
RUN set -e -x; \ RUN set -e -x; \
if [ "$REL" = "buster" ]; then \ perl -i -pe 's/deb.debian.org/archive.debian.org/' /etc/apt/sources.list; \
perl -i -pe 's/deb.debian.org/archive.debian.org/' /etc/apt/sources.list; \ apt-get update; \
apt-get update; \ apt-get -y install wget; \
apt-get -y install wget; \ wget https://vitastor.io/debian/pubkey.gpg -O /etc/apt/trusted.gpg.d/vitastor.gpg; \
wget https://vitastor.io/debian/pubkey.gpg -O /etc/apt/trusted.gpg.d/vitastor.gpg; \ echo "deb https://vitastor.io/debian $REL main" >> /etc/apt/sources.list; \
echo "deb https://vitastor.io/debian $REL main" >> /etc/apt/sources.list; \
fi; \
grep '^deb ' /etc/apt/sources.list | perl -pe 's/^deb/deb-src/' >> /etc/apt/sources.list; \ grep '^deb ' /etc/apt/sources.list | perl -pe 's/^deb/deb-src/' >> /etc/apt/sources.list; \
perl -i -pe 's/Types: deb$/Types: deb deb-src/' /etc/apt/sources.list.d/*.sources || true; \ perl -i -pe 's/Types: deb$/Types: deb deb-src/' /etc/apt/sources.list.d/*.sources || true; \
echo 'APT::Install-Recommends false;' >> /etc/apt/apt.conf; \ echo 'APT::Install-Recommends false;' >> /etc/apt/apt.conf; \
echo 'APT::Install-Suggests false;' >> /etc/apt/apt.conf echo 'APT::Install-Suggests false;' >> /etc/apt/apt.conf
RUN apt-get update && \ RUN apt-get update && \
apt-get -y install fio libgoogle-perftools-dev devscripts libjerasure-dev cmake libc-ares-dev \ apt-get -y install fio libgoogle-perftools-dev devscripts libjerasure-dev cmake libc-ares-dev libisal-crypto-dev \
libibverbs-dev librdmacm-dev libisal-dev libnl-3-dev libnl-genl-3-dev curl nodejs npm node-nan node-bindings && \ libibverbs-dev librdmacm-dev libisal-dev libnl-3-dev libnl-genl-3-dev curl nodejs npm node-nan node-bindings && \
apt-get -y build-dep fio && \ apt-get -y build-dep fio && \
apt-get --download-only source fio apt-get --download-only source fio
+4 -4
View File
@@ -25,7 +25,7 @@ Most of them can be set in /etc/vitastor/vitastor.conf and in etcd, but don't su
- [vault_timeout_ms](#vault_timeout_ms) - [vault_timeout_ms](#vault_timeout_ms)
- [vault_error_timeout_sec](#vault_error_timeout_sec) - [vault_error_timeout_sec](#vault_error_timeout_sec)
- [vault_refresh_leeway_sec](#vault_refresh_leeway_sec) - [vault_refresh_leeway_sec](#vault_refresh_leeway_sec)
- [max_aes_xts_pool_size](#max_aes_xts_pool_size) - [max_cipher_pool_size](#max_cipher_pool_size)
## etcd_client_cert ## etcd_client_cert
@@ -141,10 +141,10 @@ Time (in seconds) to wait before retrying after receiving an error from Vault.
Extra time (in seconds) before real Vault token lease_timeout to refresh it, just Extra time (in seconds) before real Vault token lease_timeout to refresh it, just
in case of system clock drift. in case of system clock drift.
## max_aes_xts_pool_size ## max_cipher_pool_size
- Type: integer - Type: integer
- Default: 256 - Default: 256
Maximum number of OpenSSL encryption contexts cached in OSD memory. Probably Maximum number of OpenSSL cipher contexts cached in OSD memory, counted separately
doesn't require modification. for each cipher and for encryption/decryption. Probably doesn't require modification.
+4 -4
View File
@@ -27,7 +27,7 @@ OSD, мониторами и клиентами.
- [vault_timeout_ms](#vault_timeout_ms) - [vault_timeout_ms](#vault_timeout_ms)
- [vault_error_timeout_sec](#vault_error_timeout_sec) - [vault_error_timeout_sec](#vault_error_timeout_sec)
- [vault_refresh_leeway_sec](#vault_refresh_leeway_sec) - [vault_refresh_leeway_sec](#vault_refresh_leeway_sec)
- [max_aes_xts_pool_size](#max_aes_xts_pool_size) - [max_cipher_pool_size](#max_cipher_pool_size)
## etcd_client_cert ## etcd_client_cert
@@ -145,10 +145,10 @@ OSD, клиенты и мониторы должны иметь разные п
Зазор времени (в секундах), чтобы обновлять токены Vault чуть раньше их реального Зазор времени (в секундах), чтобы обновлять токены Vault чуть раньше их реального
lease_timeout, на случай "ухода" системных часов. lease_timeout, на случай "ухода" системных часов.
## max_aes_xts_pool_size ## max_cipher_pool_size
- Тип: целое число - Тип: целое число
- Значение по умолчанию: 256 - Значение по умолчанию: 256
Максимальное количество кэшируемых в памяти OSD контекстов шифрования OpenSSL. Максимальное количество кэшируемых в памяти OSD контекстов шифра OpenSSL, учитываемое
Вряд ли требует изменения. отдельно для каждого шифра и для шифрования и расшифровки. Вряд ли требует изменения.
+5 -5
View File
@@ -120,12 +120,12 @@
info_ru: | info_ru: |
Зазор времени (в секундах), чтобы обновлять токены Vault чуть раньше их реального Зазор времени (в секундах), чтобы обновлять токены Vault чуть раньше их реального
lease_timeout, на случай "ухода" системных часов. lease_timeout, на случай "ухода" системных часов.
- name: max_aes_xts_pool_size - name: max_cipher_pool_size
type: int type: int
default: 256 default: 256
info: | info: |
Maximum number of OpenSSL encryption contexts cached in OSD memory. Probably Maximum number of OpenSSL cipher contexts cached in OSD memory, counted separately
doesn't require modification. for each cipher and for encryption/decryption. Probably doesn't require modification.
info_ru: | info_ru: |
Максимальное количество кэшируемых в памяти OSD контекстов шифрования OpenSSL. Максимальное количество кэшируемых в памяти OSD контекстов шифра OpenSSL, учитываемое
Вряд ли требует изменения. отдельно для каждого шифра и для шифрования и расшифровки. Вряд ли требует изменения.
+5 -3
View File
@@ -69,15 +69,17 @@ pkg_check_modules(ISAL libisal)
if (ISAL_LIBRARIES) if (ISAL_LIBRARIES)
add_definitions(-DWITH_ISAL) add_definitions(-DWITH_ISAL)
endif (ISAL_LIBRARIES) endif (ISAL_LIBRARIES)
pkg_check_modules(ISAL_CRYPTO libisal_crypto)
if (ISAL_CRYPTO_LIBRARIES)
add_definitions(-DWITH_ISAL_CRYPTO)
endif (ISAL_CRYPTO_LIBRARIES)
pkg_check_modules(RDMACM librdmacm) pkg_check_modules(RDMACM librdmacm)
if (RDMACM_LIBRARIES) if (RDMACM_LIBRARIES)
add_definitions(-DWITH_RDMACM) add_definitions(-DWITH_RDMACM)
endif (RDMACM_LIBRARIES) endif (RDMACM_LIBRARIES)
find_package(OpenSSL REQUIRED) find_package(OpenSSL REQUIRED)
if (OPENSSL_FOUND) add_definitions(-DWITH_OPENSSL)
add_definitions(-DWITH_OPENSSL)
endif (OPENSSL_FOUND)
pkg_check_modules(CARES REQUIRED libcares) pkg_check_modules(CARES REQUIRED libcares)
include_directories(${CARES_INCLUDE_DIRS}) include_directories(${CARES_INCLUDE_DIRS})
+3 -2
View File
@@ -16,7 +16,7 @@ add_library(vitastor_common STATIC
msgr_encrypt.cpp msgr_stop.cpp msgr_op.cpp msgr_send.cpp msgr_receive.cpp ../util/ringloop.cpp ../../json11/json11.cpp msgr_encrypt.cpp msgr_stop.cpp msgr_op.cpp msgr_send.cpp msgr_receive.cpp ../util/ringloop.cpp ../../json11/json11.cpp
http_client.cpp osd_ops.cpp pg_states.cpp ../util/timerfd_manager.cpp ../util/str_util.cpp ../util/json_util.cpp ${MSGR_RDMA} ${MSGR_RDMACM} http_client.cpp osd_ops.cpp pg_states.cpp ../util/timerfd_manager.cpp ../util/str_util.cpp ../util/json_util.cpp ${MSGR_RDMA} ${MSGR_RDMACM}
) )
target_link_libraries(vitastor_common pthread ${OPENSSL_LIBRARIES} ${CARES_LIBRARIES}) target_link_libraries(vitastor_common pthread ${OPENSSL_LIBRARIES} ${CARES_LIBRARIES} ${ISAL_CRYPTO_LIBRARIES})
target_compile_options(vitastor_common PUBLIC -fPIC) target_compile_options(vitastor_common PUBLIC -fPIC)
# libvitastor_client.so # libvitastor_client.so
@@ -35,6 +35,7 @@ target_link_libraries(vitastor_client
${IBVERBS_LIBRARIES} ${IBVERBS_LIBRARIES}
${RDMACM_LIBRARIES} ${RDMACM_LIBRARIES}
${OPENSSL_LIBRARIES} ${OPENSSL_LIBRARIES}
${ISAL_CRYPTO_LIBRARIES}
) )
set_target_properties(vitastor_client PROPERTIES VERSION ${VITASTOR_VERSION} SOVERSION 0) set_target_properties(vitastor_client PROPERTIES VERSION ${VITASTOR_VERSION} SOVERSION 0)
configure_file(vitastor.pc.in vitastor.pc @ONLY) configure_file(vitastor.pc.in vitastor.pc @ONLY)
@@ -103,7 +104,7 @@ add_executable(test_cluster_client
pg_states.cpp osd_ops.cpp cluster_client.cpp cluster_client_list.cpp cluster_client_wb.cpp cluster_client_icache.cpp msgr_op.cpp ../test/mock/messenger.cpp msgr_stop.cpp msgr_encrypt.cpp pg_states.cpp osd_ops.cpp cluster_client.cpp cluster_client_list.cpp cluster_client_wb.cpp cluster_client_icache.cpp msgr_op.cpp ../test/mock/messenger.cpp msgr_stop.cpp msgr_encrypt.cpp
etcd_state_client.cpp ../util/timerfd_manager.cpp ../util/addr_util.cpp ../util/str_util.cpp ../util/json_util.cpp ../util/xxh_x86dispatch.c ../../json11/json11.cpp etcd_state_client.cpp ../util/timerfd_manager.cpp ../util/addr_util.cpp ../util/str_util.cpp ../util/json_util.cpp ../util/xxh_x86dispatch.c ../../json11/json11.cpp
) )
target_link_libraries(test_cluster_client ${OPENSSL_LIBRARIES}) target_link_libraries(test_cluster_client ${OPENSSL_LIBRARIES} ${ISAL_CRYPTO_LIBRARIES})
target_compile_definitions(test_cluster_client PUBLIC -D__MOCK__) target_compile_definitions(test_cluster_client PUBLIC -D__MOCK__)
target_include_directories(test_cluster_client BEFORE PUBLIC ${CMAKE_SOURCE_DIR}/src/test/mock) target_include_directories(test_cluster_client BEFORE PUBLIC ${CMAKE_SOURCE_DIR}/src/test/mock)
add_dependencies(build_tests test_cluster_client) add_dependencies(build_tests test_cluster_client)
+31 -32
View File
@@ -16,12 +16,10 @@
#include "msgr_rdma.h" #include "msgr_rdma.h"
#endif #endif
#include "http_client.h" #include "http_client.h"
#ifdef WITH_OPENSSL
#include <openssl/bio.h> #include <openssl/bio.h>
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/pem.h> #include <openssl/pem.h>
#include <openssl/ssl.h> #include <openssl/ssl.h>
#endif
#include <sys/poll.h> #include <sys/poll.h>
@@ -128,11 +126,6 @@ void osd_messenger_t::init()
if (!tls_cert.empty() || !tls_key.empty() || !osd_tls_ca.empty() || !client_tls_ca.empty()) if (!tls_cert.empty() || !tls_key.empty() || !osd_tls_ca.empty() || !client_tls_ca.empty())
{ {
// Initialize TLS context // Initialize TLS context
// FIXME: require OpenSSL
#ifndef WITH_OPENSSL
fprintf(stderr, "Vitastor is built without OpenSSL support\n");
exit(1);
#else
if (tls_cert.empty() || tls_key.empty() || osd_tls_ca.empty() || osd_num && client_tls_ca.empty()) if (tls_cert.empty() || tls_key.empty() || osd_tls_ca.empty() || osd_num && client_tls_ca.empty())
{ {
if (osd_num) if (osd_num)
@@ -167,7 +160,6 @@ init_err:
goto init_err; goto init_err;
} }
} }
#endif
} }
#ifdef WITH_RDMACM #ifdef WITH_RDMACM
if (use_rdmacm) if (use_rdmacm)
@@ -347,21 +339,38 @@ 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_ISAL_CRYPTO
for (isal_gcm_context_data *ctx: encrypt_gcm_pool)
{
free(ctx);
}
for (isal_gcm_context_data *ctx: decrypt_gcm_pool)
{
free(ctx);
}
#else
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);
}
#endif
if (ssl_ctx) if (ssl_ctx)
{ {
SSL_CTX_free(ssl_ctx); SSL_CTX_free(ssl_ctx);
ssl_ctx = NULL; ssl_ctx = NULL;
} }
#endif
} }
void osd_messenger_t::parse_config(const json11::Json & config) void osd_messenger_t::parse_config(const json11::Json & config)
@@ -396,9 +405,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())
@@ -423,6 +432,12 @@ void osd_messenger_t::parse_config(const json11::Json & config)
test_osd_aes_key.resize(32); test_osd_aes_key.resize(32);
if (fromhexstr(config["test_osd_aes_key"].string_value(), 32, (uint8_t*)test_osd_aes_key.data()) != 32) if (fromhexstr(config["test_osd_aes_key"].string_value(), 32, (uint8_t*)test_osd_aes_key.data()) != 32)
test_osd_aes_key.clear(); test_osd_aes_key.clear();
else
{
#ifdef WITH_ISAL_CRYPTO
isal_aes_gcm_pre_256(test_osd_aes_key.data(), &test_osd_aes_key_isal);
#endif
}
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
@@ -936,23 +951,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);
} }
} }
+26 -11
View File
@@ -12,8 +12,10 @@
#include <deque> #include <deque>
#include <vector> #include <vector>
#ifdef WITH_OPENSSL
#include <openssl/types.h> #include <openssl/types.h>
#ifdef WITH_ISAL_CRYPTO
#include <isa-l_crypto/aes_gcm.h>
#endif #endif
#include "../util/xxh_x86dispatch.h" #include "../util/xxh_x86dispatch.h"
@@ -90,7 +92,6 @@ struct osd_client_t
msgr_rdma_connection_t *rdma_conn = NULL; msgr_rdma_connection_t *rdma_conn = NULL;
#endif #endif
#ifdef WITH_OPENSSL
SSL *ssl_cli = NULL; SSL *ssl_cli = NULL;
BIO *write_to_ssl = NULL; BIO *write_to_ssl = NULL;
// FIXME: use custom bio to avoid 1 more memory copy? // FIXME: use custom bio to avoid 1 more memory copy?
@@ -102,13 +103,18 @@ 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;
#ifdef WITH_ISAL_CRYPTO
isal_gcm_context_data *enc_ctx = NULL;
isal_gcm_context_data *dec_ctx = NULL;
#else
EVP_CIPHER_CTX *enc_ctx = NULL; EVP_CIPHER_CTX *enc_ctx = NULL;
EVP_CIPHER_CTX *dec_ctx = NULL;
#endif
uint8_t enc_tag[16]; uint8_t enc_tag[16];
size_t enc_tag_size = 0; size_t enc_tag_size = 0;
EVP_CIPHER_CTX *dec_ctx = NULL;
uint8_t dec_tag[16]; uint8_t dec_tag[16];
size_t dec_tag_size = 0; size_t dec_tag_size = 0;
#endif
// Read state // Read state
bool io_error = false; bool io_error = false;
@@ -123,7 +129,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;
@@ -149,7 +155,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();
@@ -254,13 +260,16 @@ 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;
std::string osd_tls_ca; std::string osd_tls_ca;
std::string client_tls_ca; std::string client_tls_ca;
std::string test_osd_aes_key; // FIXME Insecure, only for PoC tests std::string test_osd_aes_key; // FIXME Insecure, only for PoC tests
#ifdef WITH_ISAL_CRYPTO
isal_gcm_key_data test_osd_aes_key_isal;
#endif
#ifdef WITH_RDMA #ifdef WITH_RDMA
bool use_rdma = true; bool use_rdma = true;
@@ -278,13 +287,11 @@ protected:
robin_hood::unordered_flat_map<rdma_cm_id*, rdmacm_connecting_t*> rdmacm_connecting; robin_hood::unordered_flat_map<rdma_cm_id*, rdmacm_connecting_t*> rdmacm_connecting;
#endif #endif
#ifdef WITH_OPENSSL
SSL_CTX *ssl_ctx = NULL; SSL_CTX *ssl_ctx = NULL;
std::string tls_cn; std::string tls_cn;
void ssl_init(osd_client_t *cl, bool server_mode); void ssl_init(osd_client_t *cl, bool server_mode);
bool ssl_do_handshake(osd_client_t *cl); bool ssl_do_handshake(osd_client_t *cl);
#endif
std::vector<msgr_iothread_t*> iothreads; std::vector<msgr_iothread_t*> iothreads;
std::vector<uint64_t> read_ready_clients; std::vector<uint64_t> read_ready_clients;
@@ -292,8 +299,16 @@ 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;
#ifdef WITH_ISAL_CRYPTO
std::vector<isal_gcm_context_data*> encrypt_gcm_pool;
std::vector<isal_gcm_context_data*> decrypt_gcm_pool;
#else
std::vector<EVP_CIPHER_CTX*> encrypt_gcm_pool;
std::vector<EVP_CIPHER_CTX*> decrypt_gcm_pool;
#endif
public: public:
timerfd_manager_t *tfd = NULL; timerfd_manager_t *tfd = NULL;
+67 -53
View File
@@ -3,13 +3,17 @@
#include <assert.h> #include <assert.h>
#ifdef WITH_ISAL_CRYPTO
#include <isa-l_crypto/isal_crypto_api.h>
#endif
#include "etcd_state_client.h" #include "etcd_state_client.h"
#include "messenger.h" #include "messenger.h"
#include "msgr_encrypt.h" #include "msgr_encrypt.h"
op_aes_xts_encrypt_t::op_aes_xts_encrypt_t() op_aes_xts_encrypt_t::op_aes_xts_encrypt_t()
{ {
#ifdef WITH_OPENSSL #ifndef WITH_ISAL_CRYPTO
if (!(ctx = EVP_CIPHER_CTX_new())) if (!(ctx = EVP_CIPHER_CTX_new()))
{ {
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);
@@ -21,16 +25,13 @@ op_aes_xts_encrypt_t::op_aes_xts_encrypt_t()
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);
abort(); abort();
} }
#else
fprintf(stderr, "Error: Vitastor is built without encryption support\n");
abort();
#endif #endif
} }
op_aes_xts_encrypt_t::~op_aes_xts_encrypt_t() op_aes_xts_encrypt_t::~op_aes_xts_encrypt_t()
{ {
assert(!encrypted); assert(!encrypted);
#ifdef WITH_OPENSSL #ifndef WITH_ISAL_CRYPTO
EVP_CIPHER_CTX_free(ctx); EVP_CIPHER_CTX_free(ctx);
#endif #endif
if (tmp) if (tmp)
@@ -52,7 +53,7 @@ void op_aes_xts_encrypt_t::start(uint8_t *key, uint64_t start_offset, size_t blo
tmp = NULL; tmp = NULL;
tmp_size = 0; tmp_size = 0;
} }
#ifdef WITH_OPENSSL #ifndef WITH_ISAL_CRYPTO
if (EVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL) != 1) if (EVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL) != 1)
{ {
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);
@@ -63,9 +64,12 @@ void op_aes_xts_encrypt_t::start(uint8_t *key, uint64_t start_offset, size_t blo
void op_aes_xts_encrypt_t::encrypt_block(uint8_t *in, uint8_t *out) void op_aes_xts_encrypt_t::encrypt_block(uint8_t *in, uint8_t *out)
{ {
#ifdef WITH_OPENSSL
uint8_t iv[16] = { 0 }; uint8_t iv[16] = { 0 };
*((uint64_t*)iv) = start_offset + offset - offset%block_size; *((uint64_t*)iv) = start_offset + offset - offset%block_size;
#ifdef WITH_ISAL_CRYPTO
int r = isal_aes_xts_enc_256(key+32, key, iv, block_size, in, out);
assert(r == 0 || r == ISAL_CRYPTO_ERR_XTS_SAME_KEYS);
#else
if (EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv) != 1) if (EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv) != 1)
{ {
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);
@@ -98,7 +102,10 @@ void op_aes_xts_encrypt_t::update(uint8_t *in, size_t max_in, uint8_t *out, size
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)
{
encrypted = false; encrypted = false;
done_in += 1;
}
} }
else if (max_in < block_size - offset%block_size) else if (max_in < block_size - offset%block_size)
{ {
@@ -126,7 +133,7 @@ void op_aes_xts_encrypt_t::update(uint8_t *in, size_t max_in, uint8_t *out, size
encrypted = true; encrypted = true;
memcpy(out, tmp, max_out); memcpy(out, tmp, max_out);
tmp_pos = max_out; tmp_pos = max_out;
done_in += max_in; done_in += max_in-1;
offset += max_in; offset += max_in;
done_out += max_out; done_out += max_out;
} }
@@ -158,7 +165,7 @@ void destroy_aes_xts_encrypt(op_aes_xts_encrypt_t *encrypt_ctx)
op_aes_xts_decrypt_t::op_aes_xts_decrypt_t() op_aes_xts_decrypt_t::op_aes_xts_decrypt_t()
{ {
#ifdef WITH_OPENSSL #ifndef WITH_ISAL_CRYPTO
if (!(ctx = EVP_CIPHER_CTX_new())) if (!(ctx = EVP_CIPHER_CTX_new()))
{ {
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);
@@ -170,16 +177,13 @@ op_aes_xts_decrypt_t::op_aes_xts_decrypt_t()
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);
abort(); abort();
} }
#else
fprintf(stderr, "Error: Vitastor is built without encryption support\n");
abort();
#endif #endif
} }
op_aes_xts_decrypt_t::~op_aes_xts_decrypt_t() op_aes_xts_decrypt_t::~op_aes_xts_decrypt_t()
{ {
assert(!decrypted); assert(!decrypted);
#ifdef WITH_OPENSSL #ifndef WITH_ISAL_CRYPTO
EVP_CIPHER_CTX_free(ctx); EVP_CIPHER_CTX_free(ctx);
#endif #endif
if (tmp) if (tmp)
@@ -190,9 +194,9 @@ void op_aes_xts_decrypt_t::start(uint8_t **key_chain, size_t chain_size, void *k
{ {
assert(!decrypted); assert(!decrypted);
this->start_offset = start_offset; this->start_offset = start_offset;
this->key_chain = chain_size > 1 ? key_chain : 0; this->key_chain = key_chain;
this->chain_size = chain_size > 1 ? chain_size : 0; this->chain_size = chain_size;
this->key_indexes = chain_size > 1 ? key_indexes : NULL; this->key_indexes = key_indexes;
this->key_index_bytes = osd_op_rw_t::chain_info_bytes(chain_size); this->key_index_bytes = osd_op_rw_t::chain_info_bytes(chain_size);
assert(chain_size <= 1 || key_indexes != NULL); assert(chain_size <= 1 || key_indexes != NULL);
this->block_size = block_size; this->block_size = block_size;
@@ -204,7 +208,7 @@ void op_aes_xts_decrypt_t::start(uint8_t **key_chain, size_t chain_size, void *k
tmp = NULL; tmp = NULL;
tmp_size = 0; tmp_size = 0;
} }
#ifdef WITH_OPENSSL #ifndef WITH_ISAL_CRYPTO
if (chain_size == 1 && key_chain[0] && EVP_DecryptInit_ex(ctx, NULL, NULL, key_chain[0], NULL) != 1) if (chain_size == 1 && key_chain[0] && EVP_DecryptInit_ex(ctx, NULL, NULL, key_chain[0], NULL) != 1)
{ {
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);
@@ -216,7 +220,7 @@ void op_aes_xts_decrypt_t::start(uint8_t **key_chain, size_t chain_size, void *k
void op_aes_xts_decrypt_t::decrypt_block(uint8_t *in, uint8_t *out) void op_aes_xts_decrypt_t::decrypt_block(uint8_t *in, uint8_t *out)
{ {
uint8_t *key = NULL; uint8_t *key = NULL;
if (chain_size) if (chain_size > 1)
{ {
uint32_t key_index = key_index_bytes == 1 uint32_t key_index = key_index_bytes == 1
? ((uint8_t*)key_indexes)[offset/block_size] ? ((uint8_t*)key_indexes)[offset/block_size]
@@ -227,17 +231,24 @@ void op_aes_xts_decrypt_t::decrypt_block(uint8_t *in, uint8_t *out)
: UINT32_MAX)); : UINT32_MAX));
assert(key_index < chain_size); assert(key_index < chain_size);
key = key_chain[key_index]; key = key_chain[key_index];
if (!key)
{
if (in != out)
memcpy(out, in, block_size);
return;
}
} }
#ifdef WITH_OPENSSL else
{
key = key_chain[0];
}
if (!key)
{
if (in != out)
memcpy(out, in, block_size);
return;
}
uint8_t iv[16] = { 0 }; uint8_t iv[16] = { 0 };
*((uint64_t*)iv) = start_offset + offset - offset%block_size; *((uint64_t*)iv) = start_offset + offset - offset%block_size;
if (EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv) != 1) #ifdef WITH_ISAL_CRYPTO
int r = isal_aes_xts_dec_256(key+32, key, iv, block_size, in, out);
assert(r == 0 || r == ISAL_CRYPTO_ERR_XTS_SAME_KEYS);
#else
if (EVP_DecryptInit_ex(ctx, NULL, NULL, chain_size == 1 ? NULL : key, iv) != 1)
{ {
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);
abort(); abort();
@@ -272,7 +283,10 @@ void op_aes_xts_decrypt_t::update(uint8_t *in, size_t max_in, uint8_t *out, size
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)
{
decrypted = false; decrypted = false;
done_in += 1;
}
} }
else if (max_in < block_size - offset%block_size) else if (max_in < block_size - offset%block_size)
{ {
@@ -301,7 +315,7 @@ void op_aes_xts_decrypt_t::update(uint8_t *in, size_t max_in, uint8_t *out, size
if (out) if (out)
memcpy(out, tmp, max_out); memcpy(out, tmp, max_out);
tmp_pos = max_out; tmp_pos = max_out;
done_in += max_in; done_in += max_in-1;
offset += max_in; offset += max_in;
done_out += max_out; done_out += max_out;
} }
@@ -335,23 +349,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_plain < plain_len && done_enc < enc_len)
{ {
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 +382,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 +394,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 +437,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 +458,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;
} }
} }
+6 -7
View File
@@ -3,17 +3,18 @@
#include <stdint.h> #include <stdint.h>
#ifdef WITH_ISAL_CRYPTO
#include <isa-l_crypto/aes_xts.h>
#endif
#include "../util/xxh_x86dispatch.h" #include "../util/xxh_x86dispatch.h"
// WITH_OPENSSL is left to possibly support other crypto libraries
#ifdef WITH_OPENSSL
#include <openssl/conf.h> #include <openssl/conf.h>
#include <openssl/evp.h> #include <openssl/evp.h>
#include <openssl/err.h> #include <openssl/err.h>
#endif
class op_aes_xts_encrypt_t class op_aes_xts_encrypt_t
{ {
#ifdef WITH_OPENSSL #ifndef WITH_ISAL_CRYPTO
EVP_CIPHER_CTX *ctx = NULL; EVP_CIPHER_CTX *ctx = NULL;
#endif #endif
uint64_t start_offset = 0; uint64_t start_offset = 0;
@@ -31,7 +32,6 @@ public:
op_aes_xts_encrypt_t(); op_aes_xts_encrypt_t();
~op_aes_xts_encrypt_t(); ~op_aes_xts_encrypt_t();
inline bool has_buffered() { return encrypted; };
void start(uint8_t *key, uint64_t start_offset, size_t block_size); void start(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);
}; };
@@ -40,7 +40,7 @@ void destroy_aes_xts_encrypt(op_aes_xts_encrypt_t *encrypt_ctx);
class op_aes_xts_decrypt_t class op_aes_xts_decrypt_t
{ {
#ifdef WITH_OPENSSL #ifndef WITH_ISAL_CRYPTO
EVP_CIPHER_CTX *ctx = NULL; EVP_CIPHER_CTX *ctx = NULL;
#endif #endif
uint64_t start_offset = 0; uint64_t start_offset = 0;
@@ -61,7 +61,6 @@ public:
op_aes_xts_decrypt_t(); op_aes_xts_decrypt_t();
~op_aes_xts_decrypt_t(); ~op_aes_xts_decrypt_t();
inline bool has_buffered() { return decrypted; };
void start(uint8_t **key_chain, size_t chain_size, void *key_indexes, uint64_t start_offset, size_t block_size); void start(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);
}; };
+30 -1
View File
@@ -590,7 +590,36 @@ void osd_messenger_t::try_send_rdma(osd_client_t *cl)
while (!rc->send_out_full && copied > 0 && rc->cur_send < rc->max_send) while (!rc->send_out_full && copied > 0 && rc->cur_send < rc->max_send)
{ {
dst = (uint8_t*)rc->send_out.buf + rc->send_out_pos; dst = (uint8_t*)rc->send_out.buf + rc->send_out_pos;
dst_len = (rc->send_out_pos < rc->send_out_size ? rc->send_out_size-rc->send_out_pos : rc->send_done_pos-rc->send_out_pos); if (rc->send_out_pos >= rc->send_done_pos)
{
dst_len = rc->send_out_size-rc->send_out_pos;
if (dst_len < 4096)
{
// free end of the buffer is too small, skip
rc->send_out_pos = 0;
if (rc->send_out_pos >= rc->send_done_pos)
rc->send_out_full = true;
if (!rc->send_sizes.size())
{
rc->send_done_pos += dst_len;
rc->send_out_full = false;
if (rc->send_done_pos == rc->send_out_size)
rc->send_done_pos = 0;
}
else
rc->send_sizes.back() += dst_len;
continue;
}
}
else
{
dst_len = rc->send_done_pos-rc->send_out_pos;
if (dst_len < 4096)
{
// too small buffer, stop
break;
}
}
if (dst_len > rc->max_msg) if (dst_len > rc->max_msg)
dst_len = rc->max_msg; dst_len = rc->max_msg;
copied = copy_ops_to(cl, dst, dst_len); copied = copy_ops_to(cl, dst, dst_len);
+75 -8
View File
@@ -5,12 +5,10 @@
#include <limits.h> #include <limits.h>
#include "messenger.h" #include "messenger.h"
#ifdef WITH_OPENSSL
#include <openssl/bio.h> #include <openssl/bio.h>
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/pem.h> #include <openssl/pem.h>
#include <openssl/ssl.h> #include <openssl/ssl.h>
#endif
#define RDR_TLS 1 #define RDR_TLS 1
#define RDR_XTS 2 #define RDR_XTS 2
@@ -287,7 +285,39 @@ 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
{
#ifdef WITH_ISAL_CRYPTO
cl->dec_ctx = (isal_gcm_context_data*)malloc_or_die(sizeof(isal_gcm_context_data));
#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();
}
#endif
}
}
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 };
#ifdef WITH_ISAL_CRYPTO
int r = isal_aes_gcm_init_256(&msgr->test_osd_aes_key_isal, cl->dec_ctx, iv, NULL, 0);
if (r != 0)
{
fprintf(stderr, "isal_aes_gcm_init_256 error %d\n", r);
abort();
}
#else
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)
{ {
@@ -295,6 +325,7 @@ public:
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);
abort(); abort();
} }
#endif
} }
bool read(uint8_t *dst, size_t dst_len, int flags) override bool read(uint8_t *dst, size_t dst_len, int flags) override
@@ -343,6 +374,10 @@ public:
size_t n = dst_len-from; size_t n = dst_len-from;
if (n > bufsize-done) if (n > bufsize-done)
n = bufsize-done; n = bufsize-done;
#ifdef WITH_ISAL_CRYPTO
int r = isal_aes_gcm_dec_256_update(&msgr->test_osd_aes_key_isal, cl->dec_ctx, dst+from, curbuf+done, n);
assert(!r);
#else
int actual_out; int actual_out;
if (EVP_DecryptUpdate(cl->dec_ctx, dst+from, &actual_out, curbuf+done, n) != 1) if (EVP_DecryptUpdate(cl->dec_ctx, dst+from, &actual_out, curbuf+done, n) != 1)
{ {
@@ -351,6 +386,7 @@ public:
abort(); abort();
} }
assert(actual_out == n); assert(actual_out == n);
#endif
if (cl->read_csum_state && !(flags & RDR_NO_CSUM)) if (cl->read_csum_state && !(flags & RDR_NO_CSUM))
{ {
XXH3_64bits_update(cl->read_csum_state, dst+from, n); XXH3_64bits_update(cl->read_csum_state, dst+from, n);
@@ -377,31 +413,62 @@ public:
done = bufsize; done = bufsize;
return false; return false;
} }
#ifdef WITH_ISAL_CRYPTO
uint8_t calc_tag[16];
int r = isal_aes_gcm_dec_256_finalize(&msgr->test_osd_aes_key_isal, cl->dec_ctx, calc_tag, 16);
assert(r == 0);
if (cl->dec_tag_size > 0)
{
// Tag is partially buffered, append to it and compare
memcpy(cl->dec_tag+cl->dec_tag_size, curbuf+done, 16-cl->dec_tag_size);
done += 16-cl->dec_tag_size;
r = !memcmp(calc_tag, cl->dec_tag, 16);
}
else
{
// Compare the full tag directly from the source buffer
r = !memcmp(calc_tag, curbuf+done, 16);
done += 16;
}
#else
int r; int r;
if (cl->dec_tag_size > 0) if (cl->dec_tag_size > 0)
{ {
// Tag is partially buffered, append to it and use it from there // Tag is partially buffered, append to it and use it from there
memcpy(cl->dec_tag+cl->dec_tag_size, curbuf+done, 16-cl->dec_tag_size); memcpy(cl->dec_tag+cl->dec_tag_size, curbuf+done, 16-cl->dec_tag_size);
done += 16-cl->dec_tag_size;
r = EVP_CIPHER_CTX_ctrl(cl->dec_ctx, EVP_CTRL_GCM_SET_TAG, 16, cl->dec_tag); r = EVP_CIPHER_CTX_ctrl(cl->dec_ctx, EVP_CTRL_GCM_SET_TAG, 16, cl->dec_tag);
assert(r == 1);
done += 16-cl->dec_tag_size;
} }
else else
{ {
// Take full tag directly from the source buffer // Take full tag directly from the source buffer
r = EVP_CIPHER_CTX_ctrl(cl->dec_ctx, EVP_CTRL_GCM_SET_TAG, 16, curbuf+done); r = EVP_CIPHER_CTX_ctrl(cl->dec_ctx, EVP_CTRL_GCM_SET_TAG, 16, curbuf+done);
assert(r == 1);
done += 16; done += 16;
} }
assert(r == 1);
int len = 0; int len = 0;
r = EVP_DecryptFinal_ex(cl->dec_ctx, NULL, &len); r = EVP_DecryptFinal_ex(cl->dec_ctx, NULL, &len);
assert(len == 0);
#endif
if (r != 1) if (r != 1)
{ {
fprintf(stderr, "Client %ju AES-GCM decryption failed\n", cl->client_id); fprintf(stderr, "Client %ju AES-GCM decryption failed\n", cl->client_id);
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
{
#ifdef WITH_ISAL_CRYPTO
free(cl->dec_ctx);
#else
EVP_CIPHER_CTX_free(cl->dec_ctx);
#endif
}
cl->dec_ctx = NULL;
cl->dec_tag_size = 0; cl->dec_tag_size = 0;
assert(len == 0);
return true; return true;
} }
@@ -461,7 +528,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)
{ {
@@ -495,7 +562,7 @@ public:
bool finish() override bool finish() override
{ {
if (cl->dec_ctx) if (cl->gcm_enabled)
return false; return false;
return true; return true;
} }
@@ -691,7 +758,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);
} }
+111 -35
View File
@@ -7,12 +7,10 @@
#include "messenger.h" #include "messenger.h"
#ifdef WITH_OPENSSL
#include <openssl/bio.h> #include <openssl/bio.h>
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/pem.h> #include <openssl/pem.h>
#include <openssl/ssl.h> #include <openssl/ssl.h>
#endif
#define WR_TLS 1 #define WR_TLS 1
#define WR_XTS 2 #define WR_XTS 2
@@ -246,7 +244,44 @@ 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
{
#ifdef WITH_ISAL_CRYPTO
cl->enc_ctx = (isal_gcm_context_data*)malloc_or_die(sizeof(isal_gcm_context_data));
#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();
}
#endif
}
}
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 };
#ifdef WITH_ISAL_CRYPTO
int r = isal_aes_gcm_init_256(&msgr->test_osd_aes_key_isal, cl->enc_ctx, iv, NULL, 0);
if (r != 0)
{
fprintf(stderr, "isal_aes_gcm_init_256 error %d\n", r);
abort();
}
#else
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)
{ {
@@ -254,6 +289,22 @@ public:
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);
abort(); abort();
} }
#endif
}
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
{
#ifdef WITH_ISAL_CRYPTO
free(cl->enc_ctx);
#else
EVP_CIPHER_CTX_free(cl->enc_ctx);
#endif
}
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
@@ -291,6 +342,10 @@ public:
n = bufsize-done; n = bufsize-done;
if (!n) if (!n)
return false; return false;
#ifdef WITH_ISAL_CRYPTO
int r = isal_aes_gcm_enc_256_update(&msgr->test_osd_aes_key_isal, cl->enc_ctx, curbuf+done, src+from, n);
assert(!r);
#else
int actual_out; int actual_out;
if (EVP_EncryptUpdate(cl->enc_ctx, curbuf+done, &actual_out, src+from, n) != 1) if (EVP_EncryptUpdate(cl->enc_ctx, curbuf+done, &actual_out, src+from, n) != 1)
{ {
@@ -299,6 +354,7 @@ public:
abort(); abort();
} }
assert(actual_out == n); assert(actual_out == n);
#endif
if (cl->write_csum_state && !(flags & WR_NO_CSUM)) if (cl->write_csum_state && !(flags & WR_NO_CSUM))
XXH3_64bits_update(cl->write_csum_state, src+from, n); XXH3_64bits_update(cl->write_csum_state, src+from, n);
done += n; done += n;
@@ -311,8 +367,12 @@ public:
return true; return true;
} }
static void write_tag_to(osd_client_t *cl, uint8_t *dst) static void write_tag_to(osd_messenger_t *msgr, osd_client_t *cl, uint8_t *dst)
{ {
#ifdef WITH_ISAL_CRYPTO
int r = isal_aes_gcm_enc_256_finalize(&msgr->test_osd_aes_key_isal, cl->enc_ctx, dst, 16);
assert(!r);
#else
int actual_out = 0; int actual_out = 0;
int r = EVP_EncryptFinal_ex(cl->enc_ctx, NULL, &actual_out); int r = EVP_EncryptFinal_ex(cl->enc_ctx, NULL, &actual_out);
if (r != 1) if (r != 1)
@@ -324,6 +384,7 @@ public:
assert(actual_out == 0); assert(actual_out == 0);
r = EVP_CIPHER_CTX_ctrl(cl->enc_ctx, EVP_CTRL_GCM_GET_TAG, 16, dst); r = EVP_CIPHER_CTX_ctrl(cl->enc_ctx, EVP_CTRL_GCM_GET_TAG, 16, dst);
assert(r == 1); assert(r == 1);
#endif
} }
bool finish() override bool finish() override
@@ -336,7 +397,7 @@ public:
// No space for the full tag, but msgr_rdma expects us to always fill the whole buffer // No space for the full tag, but msgr_rdma expects us to always fill the whole buffer
if (!cl->enc_tag_size) if (!cl->enc_tag_size)
{ {
write_tag_to(cl, cl->enc_tag); write_tag_to(msgr, cl, cl->enc_tag);
cl->enc_tag_size = 16; cl->enc_tag_size = 16;
} }
size_t n = bufsize-done; size_t n = bufsize-done;
@@ -345,11 +406,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(msgr, cl, curbuf+done);
done += 16;
}
free_ctx(msgr, cl);
return true; return true;
} }
@@ -377,32 +443,46 @@ class get_op_writer_t: public msgr_op_writer_t
min_cap = 16384; min_cap = 16384;
if (cl->ssl_out_buf_cap < min_cap) if (cl->ssl_out_buf_cap < min_cap)
{ {
uint8_t *old_buf = cl->ssl_out_buf; uintptr_t old_buf = (uintptr_t)cl->ssl_out_buf;
uint8_t *old_end = old_buf + cl->ssl_out_buf_cap; 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 = (uint8_t*)realloc_or_die(cl->ssl_out_buf, min_cap);
cl->ssl_out_buf_cap = min_cap; cl->ssl_out_buf_cap = min_cap;
for (auto & iov: cl->send_list) for (auto & iov: cl->send_list)
{ {
if (iov.iov_base >= old_buf && iov.iov_base < old_end) if ((uintptr_t)iov.iov_base >= old_buf && (uintptr_t)iov.iov_base < old_end)
iov.iov_base = cl->ssl_out_buf + ((uint8_t*)iov.iov_base - old_buf); iov.iov_base = cl->ssl_out_buf + ((uintptr_t)iov.iov_base - old_buf);
} }
} }
} }
void send_out_buf(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 copy_ssl() void copy_ssl()
{ {
size_t prev_size = cl->ssl_out_buf_size; size_t n = 0;
do do
{ {
ssl_extend_buf(); ssl_extend_buf();
int r = BIO_read(cl->read_from_ssl, cl->ssl_out_buf+cl->ssl_out_buf_size, cl->ssl_out_buf_cap-cl->ssl_out_buf_size); int r = BIO_read(cl->read_from_ssl, cl->ssl_out_buf+cl->ssl_out_buf_size, cl->ssl_out_buf_cap-cl->ssl_out_buf_size);
if (r > 0) if (r > 0)
cl->ssl_out_buf_size += r; n += r;
} while (cl->ssl_out_buf_size >= cl->ssl_out_buf_cap); } while (cl->ssl_out_buf_size+n >= cl->ssl_out_buf_cap);
if (cl->ssl_out_buf_size > prev_size) if (n > 0)
{ send_out_buf(n);
cl->send_list.push_back((iovec){ .iov_base = cl->ssl_out_buf+prev_size, .iov_len = cl->ssl_out_buf_size-prev_size });
}
} }
public: public:
@@ -416,16 +496,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();
}
} }
} }
@@ -481,6 +554,10 @@ public:
// Encrypt data to client's temporary output buffer (all at once) // Encrypt data to client's temporary output buffer (all at once)
size_t n = src_len-from; size_t n = src_len-from;
ssl_extend_buf(n); ssl_extend_buf(n);
#ifdef WITH_ISAL_CRYPTO
int r = isal_aes_gcm_enc_256_update(&msgr->test_osd_aes_key_isal, cl->enc_ctx, cl->ssl_out_buf+cl->ssl_out_buf_size, src+from, n);
assert(!r);
#else
int actual_out; int actual_out;
if (EVP_EncryptUpdate(cl->enc_ctx, cl->ssl_out_buf+cl->ssl_out_buf_size, &actual_out, src+from, n) != 1) if (EVP_EncryptUpdate(cl->enc_ctx, cl->ssl_out_buf+cl->ssl_out_buf_size, &actual_out, src+from, n) != 1)
{ {
@@ -489,10 +566,10 @@ public:
abort(); abort();
} }
assert(actual_out == n); assert(actual_out == n);
#endif
if (cl->write_csum_state && !(flags & WR_NO_CSUM)) if (cl->write_csum_state && !(flags & WR_NO_CSUM))
XXH3_64bits_update(cl->write_csum_state, src+from, n); XXH3_64bits_update(cl->write_csum_state, src+from, n);
cl->send_list.push_back((iovec){ .iov_base = cl->ssl_out_buf+cl->ssl_out_buf_size, .iov_len = n }); send_out_buf(n);
cl->ssl_out_buf_size += n;
cl->write_op_pos += n; cl->write_op_pos += n;
from += n; from += n;
if (from < src_len) if (from < src_len)
@@ -546,10 +623,9 @@ public:
return false; return false;
// Tag is 16 bytes // Tag is 16 bytes
ssl_extend_buf(16); ssl_extend_buf(16);
gcm_op_writer_t::write_tag_to(cl, cl->ssl_out_buf+cl->ssl_out_buf_size); gcm_op_writer_t::write_tag_to(msgr, cl, cl->ssl_out_buf+cl->ssl_out_buf_size);
// FIXME coalesce entries in ssl_out_buf send_out_buf(16);
cl->send_list.push_back((iovec){ .iov_base = cl->ssl_out_buf+cl->ssl_out_buf_size, .iov_len = 16 }); gcm_op_writer_t::free_ctx(msgr, cl);
cl->ssl_out_buf_size += 16;
} }
return true; return true;
} }
@@ -790,7 +866,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);
} }
+18 -14
View File
@@ -9,12 +9,10 @@
#ifdef WITH_RDMA #ifdef WITH_RDMA
#include "msgr_rdma.h" #include "msgr_rdma.h"
#endif #endif
#ifdef WITH_OPENSSL
#include <openssl/bio.h> #include <openssl/bio.h>
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/pem.h> #include <openssl/pem.h>
#include <openssl/ssl.h> #include <openssl/ssl.h>
#endif
void osd_client_t::cancel_ops() void osd_client_t::cancel_ops()
{ {
@@ -86,21 +84,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++;
@@ -248,15 +246,22 @@ osd_client_t::~osd_client_t()
XXH3_freeState(write_csum_state); XXH3_freeState(write_csum_state);
write_csum_state = NULL; write_csum_state = NULL;
} }
#ifdef WITH_OPENSSL
if (enc_ctx) if (enc_ctx)
{ {
#ifdef WITH_ISAL_CRYPTO
free(enc_ctx);
#else
EVP_CIPHER_CTX_free(enc_ctx); EVP_CIPHER_CTX_free(enc_ctx);
#endif
enc_ctx = NULL; enc_ctx = NULL;
} }
if (dec_ctx) if (dec_ctx)
{ {
#ifdef WITH_ISAL_CRYPTO
free(dec_ctx);
#else
EVP_CIPHER_CTX_free(dec_ctx); EVP_CIPHER_CTX_free(dec_ctx);
#endif
dec_ctx = NULL; dec_ctx = NULL;
} }
if (ssl_cli) if (ssl_cli)
@@ -271,5 +276,4 @@ osd_client_t::~osd_client_t()
free(ssl_out_buf); free(ssl_out_buf);
ssl_out_buf = NULL; ssl_out_buf = NULL;
} }
#endif
} }
-4
View File
@@ -1,9 +1,7 @@
// Copyright (c) Vitaliy Filippov, 2019+ // Copyright (c) Vitaliy Filippov, 2019+
// License: VNPL-1.1 (see README.md for details) // License: VNPL-1.1 (see README.md for details)
#ifdef WITH_OPENSSL
#include <openssl/rand.h> #include <openssl/rand.h>
#endif
#include <ctype.h> #include <ctype.h>
#include "cli.h" #include "cli.h"
@@ -628,14 +626,12 @@ std::function<bool(cli_result_t &)> cli_tool_t::start_create(json11::Json cfg)
if (!cfg["enc_key"].is_null()) if (!cfg["enc_key"].is_null())
{ {
image_creator->set_key = true; image_creator->set_key = true;
#ifdef WITH_OPENSSL
if (image_creator->enc_key == "random") if (image_creator->enc_key == "random")
{ {
uint8_t newkey[64]; uint8_t newkey[64];
RAND_bytes(newkey, 64); RAND_bytes(newkey, 64);
image_creator->enc_key = tohexstr(newkey, 64); image_creator->enc_key = tohexstr(newkey, 64);
} }
#endif
else else
{ {
image_creator->enc_key = cfg["enc_key"].string_value(); image_creator->enc_key = cfg["enc_key"].string_value();
-6
View File
@@ -1,9 +1,7 @@
// Copyright (c) Vitaliy Filippov, 2019+ // Copyright (c) Vitaliy Filippov, 2019+
// License: VNPL-1.1 (see README.md for details) // License: VNPL-1.1 (see README.md for details)
#ifdef WITH_OPENSSL
#include <openssl/rand.h> #include <openssl/rand.h>
#endif
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@@ -556,7 +554,6 @@ void test_writeback_merge()
printf("[ok] writeback merge test\n"); printf("[ok] writeback merge test\n");
} }
#ifdef WITH_OPENSSL
void test_msgr_encrypt() void test_msgr_encrypt()
{ {
const size_t sz = 1048576; const size_t sz = 1048576;
@@ -725,7 +722,6 @@ void test_msgr_decrypt_chain()
free(src); free(src);
printf("[ok] msgr aes-xts chained decrypt\n"); printf("[ok] msgr aes-xts chained decrypt\n");
} }
#endif
void test_vault() void test_vault()
{ {
@@ -794,10 +790,8 @@ int main(int narg, char *args[])
test2(); test2();
test_writeback(); test_writeback();
test_writeback_merge(); test_writeback_merge();
#ifdef WITH_OPENSSL
test_msgr_encrypt(); test_msgr_encrypt();
test_msgr_decrypt_chain(); test_msgr_decrypt_chain();
#endif
test_vault(); test_vault();
return 0; return 0;
} }