Compare commits

..
Author SHA1 Message Date
Vitaliy Filippov 62826a4627 WIP Batch encrypted records to reduce EncryptInit/EncryptFinal costs 2026-04-19 12:29:27 +00:00
Vitaliy Filippov 35e7bc8aeb Try to run tests with AES-GCM 2026-04-18 20:41:49 +03:00
Vitaliy Filippov 9a5fabddb4 Implement direct AES-256-GCM with a static key for benchmark 2026-04-18 20:41:49 +03:00
Vitaliy Filippov 088e85a423 Make sure to send all TLS data before continuing 2026-04-18 14:22:42 +03:00
Vitaliy Filippov 43f1d58f29 Parse standard TLS record headers 2026-04-17 21:22:47 +03:00
Vitaliy Filippov a6b29a01a2 Omit msgr_tls_record_hdr_t for non-tls data 2026-04-17 21:22:47 +03:00
Vitaliy Filippov 5d65d87dfb Allow 2 and 4 byte per block chain_info (allow more than 255 snapshots with encryption) 2026-04-17 21:22:47 +03:00
Vitaliy Filippov ddf28feaf8 Implement OSD TLS support 2026-04-17 21:22:47 +03:00
Vitaliy Filippov a57049be63 Allow to skip checksums for headers 2026-04-17 13:53:41 +03:00
Vitaliy Filippov 7f53e315c5 Implement protocol-level checksums (xxhash3) 2026-04-17 13:53:41 +03:00
Vitaliy Filippov 48756520dd Include xxhash3 x86dispatch 2026-04-17 13:53:41 +03:00
Vitaliy Filippov 4f23b242f3 Do not use scrap_buffer in the client (it would block protocol checksum support) 2026-04-17 13:53:41 +03:00
Vitaliy Filippov c371b74e12 Support TLS CN authentication and per-image permissions in vitastor-cli serve 2026-04-17 13:53:41 +03:00
Vitaliy Filippov c014d20fca Add VitastorAuthFilter 2026-04-17 13:53:41 +03:00
Vitaliy Filippov 9b2480d552 Implement vitastor-cli ls-user, modify-user, remove-user commands 2026-04-17 13:53:40 +03:00
Vitaliy Filippov 1ae10c21ca Add image owner/owner_group/reader_group support (for antietcd VitastorAuthFilter) 2026-04-17 13:53:40 +03:00
Vitaliy Filippov 4698009b59 Add security parameter documentation 2026-04-17 13:53:40 +03:00
Vitaliy Filippov d0e0b70f81 Support inline (string PEM) certificates and pkeys 2026-04-17 13:53:40 +03:00
Vitaliy Filippov 914f42da5c Show encryption keys (only IDs) in the listing 2026-04-17 13:53:40 +03:00
Vitaliy Filippov 273b641820 Support storing image encryption keys in Vault 2026-04-17 13:53:40 +03:00
Vitaliy Filippov 4f9de7a6fb Prefer local etcd addresses and correctly cycle over them even when they need resolving
Seems slightly overcomplicated...
2026-04-17 13:53:40 +03:00
Vitaliy Filippov d3c529abd7 Support DNS resolving via libc-ares 2026-04-17 13:53:40 +03:00
Vitaliy Filippov a8e19ba28a Batch handle_immediate_ops more 2026-04-17 13:53:40 +03:00
Vitaliy Filippov 64a8cd1f4b Add vitastor-cli create & modify --enc-key parameter 2026-04-17 13:53:40 +03:00
Vitaliy Filippov cc6e531410 Support reading from snapshots encrypted with different keys 2026-04-17 13:53:40 +03:00
Vitaliy Filippov ca608d0b87 Support decryption with multiple keys 2026-04-17 13:53:40 +03:00
Vitaliy Filippov 0e095d2347 Allow to return chain_info in response to reads 2026-04-17 13:53:40 +03:00
Vitaliy Filippov 4fe2a0a3eb Add basic AES-XTS client-side encryption support 2026-04-17 13:53:40 +03:00
Vitaliy Filippov 1a4d275616 Rework msgr send/receive to allow encryption support 2026-04-17 13:53:40 +03:00
Vitaliy Filippov 803c870493 Move fromhexstr() to str_util 2026-04-17 13:53:40 +03:00
Vitaliy Filippov 0d97fba466 Add openapi description 2026-04-17 13:53:40 +03:00
Vitaliy Filippov 41100260ec Slightly fix API return and input types 2026-04-17 13:53:40 +03:00
Vitaliy Filippov 07c9606594 Implement vitastor-cli serve command to serve simple HTTP API 2026-04-17 13:53:40 +03:00
Vitaliy Filippov 4ba361d83d Implement HTTP server support O_o 2026-04-17 13:53:40 +03:00
Vitaliy Filippov 662fb86eae Rename http_response_t to http_message_t 2026-04-17 13:53:40 +03:00
Vitaliy Filippov 1df8b51abb Extract common HTTP context 2026-04-17 13:53:40 +03:00
Vitaliy Filippov d2d01e5183 Support xxhash 32-bit checksums (data_csum_type=xxh3_32) 2026-04-17 13:53:40 +03:00
Vitaliy Filippov 3d96c3907e Detect block checksums using csum_block_size, not data_csum_type 2026-04-17 13:53:40 +03:00
Vitaliy Filippov fb483185ff Add client certificate support 2026-04-17 13:53:40 +03:00
Vitaliy Filippov d6eb00e18e Do not re-initialize TLS context every connection 2026-04-17 13:53:40 +03:00
Vitaliy Filippov 34d47bd62a Add https support to antietcd 2026-04-17 13:53:40 +03:00
Vitaliy Filippov 2846eba3af Implement etcd SSL support via OpenSSL
Maybe I should remove all of this and use libwebsockets :)
2026-04-17 13:53:40 +03:00
30 changed files with 755 additions and 1087 deletions
+8 -6
View File
@@ -12,18 +12,20 @@ ARG REL=
WORKDIR /root
RUN set -e -x; \
perl -i -pe 's/deb.debian.org/archive.debian.org/' /etc/apt/sources.list; \
apt-get update; \
apt-get -y install wget; \
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; \
if [ "$REL" = "buster" ]; then \
perl -i -pe 's/deb.debian.org/archive.debian.org/' /etc/apt/sources.list; \
apt-get update; \
apt-get -y install wget; \
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; \
fi; \
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; \
echo 'APT::Install-Recommends false;' >> /etc/apt/apt.conf; \
echo 'APT::Install-Suggests false;' >> /etc/apt/apt.conf
RUN apt-get update && \
apt-get -y install fio libgoogle-perftools-dev devscripts libjerasure-dev cmake libc-ares-dev libisal-crypto-dev \
apt-get -y install fio libgoogle-perftools-dev devscripts libjerasure-dev cmake libc-ares-dev \
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 --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_error_timeout_sec](#vault_error_timeout_sec)
- [vault_refresh_leeway_sec](#vault_refresh_leeway_sec)
- [max_cipher_pool_size](#max_cipher_pool_size)
- [max_aes_xts_pool_size](#max_aes_xts_pool_size)
## 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
in case of system clock drift.
## max_cipher_pool_size
## max_aes_xts_pool_size
- Type: integer
- Default: 256
Maximum number of OpenSSL cipher contexts cached in OSD memory, counted separately
for each cipher and for encryption/decryption. Probably doesn't require modification.
Maximum number of OpenSSL encryption contexts cached in OSD memory. Probably
doesn't require modification.
+4 -4
View File
@@ -27,7 +27,7 @@ OSD, мониторами и клиентами.
- [vault_timeout_ms](#vault_timeout_ms)
- [vault_error_timeout_sec](#vault_error_timeout_sec)
- [vault_refresh_leeway_sec](#vault_refresh_leeway_sec)
- [max_cipher_pool_size](#max_cipher_pool_size)
- [max_aes_xts_pool_size](#max_aes_xts_pool_size)
## etcd_client_cert
@@ -145,10 +145,10 @@ OSD, клиенты и мониторы должны иметь разные п
Зазор времени (в секундах), чтобы обновлять токены Vault чуть раньше их реального
lease_timeout, на случай "ухода" системных часов.
## max_cipher_pool_size
## max_aes_xts_pool_size
- Тип: целое число
- Значение по умолчанию: 256
Максимальное количество кэшируемых в памяти OSD контекстов шифра OpenSSL, учитываемое
отдельно для каждого шифра и для шифрования и расшифровки. Вряд ли требует изменения.
Максимальное количество кэшируемых в памяти OSD контекстов шифрования OpenSSL.
Вряд ли требует изменения.
+5 -5
View File
@@ -120,12 +120,12 @@
info_ru: |
Зазор времени (в секундах), чтобы обновлять токены Vault чуть раньше их реального
lease_timeout, на случай "ухода" системных часов.
- name: max_cipher_pool_size
- name: max_aes_xts_pool_size
type: int
default: 256
info: |
Maximum number of OpenSSL cipher contexts cached in OSD memory, counted separately
for each cipher and for encryption/decryption. Probably doesn't require modification.
Maximum number of OpenSSL encryption contexts cached in OSD memory. Probably
doesn't require modification.
info_ru: |
Максимальное количество кэшируемых в памяти OSD контекстов шифра OpenSSL, учитываемое
отдельно для каждого шифра и для шифрования и расшифровки. Вряд ли требует изменения.
Максимальное количество кэшируемых в памяти OSD контекстов шифрования OpenSSL.
Вряд ли требует изменения.
-1
View File
@@ -262,4 +262,3 @@ Options:
| `--logfile <FILE>` | log to the specified file |
| `--enforce 1` | enforce permissions at the server side (no by default) |
| `--foreground 1` | stay in foreground, do not daemonize |
| `--trace` | trace all NFS requests |
-1
View File
@@ -274,4 +274,3 @@ VitastorFS из GPUDirect.
| `--logfile <FILE>` | записывать логи в заданный файл |
| `--enforce 1` | проверять права доступа на стороне сервера (по умолчанию нет) |
| `--foreground 1` | не уходить в фон после запуска |
| `--trace` | логгировать все запросы NFS |
+3 -5
View File
@@ -69,17 +69,15 @@ pkg_check_modules(ISAL libisal)
if (ISAL_LIBRARIES)
add_definitions(-DWITH_ISAL)
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)
if (RDMACM_LIBRARIES)
add_definitions(-DWITH_RDMACM)
endif (RDMACM_LIBRARIES)
find_package(OpenSSL REQUIRED)
add_definitions(-DWITH_OPENSSL)
if (OPENSSL_FOUND)
add_definitions(-DWITH_OPENSSL)
endif (OPENSSL_FOUND)
pkg_check_modules(CARES REQUIRED libcares)
include_directories(${CARES_INCLUDE_DIRS})
+4 -5
View File
@@ -12,11 +12,11 @@ if (RDMACM_LIBRARIES)
set(MSGR_RDMACM "msgr_rdmacm.cpp")
endif (RDMACM_LIBRARIES)
add_library(vitastor_common STATIC
../util/epoll_manager.cpp etcd_state_client.cpp messenger.cpp ../util/addr_util.cpp ../util/xxh_x86dispatch.c ../util/openssl_util.cpp
../util/epoll_manager.cpp etcd_state_client.cpp messenger.cpp ../util/addr_util.cpp ../util/xxh_x86dispatch.c
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}
)
target_link_libraries(vitastor_common pthread ${OPENSSL_LIBRARIES} ${CARES_LIBRARIES} ${ISAL_CRYPTO_LIBRARIES})
target_link_libraries(vitastor_common pthread ${OPENSSL_LIBRARIES} ${CARES_LIBRARIES})
target_compile_options(vitastor_common PUBLIC -fPIC)
# libvitastor_client.so
@@ -35,7 +35,6 @@ target_link_libraries(vitastor_client
${IBVERBS_LIBRARIES}
${RDMACM_LIBRARIES}
${OPENSSL_LIBRARIES}
${ISAL_CRYPTO_LIBRARIES}
)
set_target_properties(vitastor_client PROPERTIES VERSION ${VITASTOR_VERSION} SOVERSION 0)
configure_file(vitastor.pc.in vitastor.pc @ONLY)
@@ -102,9 +101,9 @@ add_executable(test_cluster_client
EXCLUDE_FROM_ALL
../test/test_cluster_client.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 ../util/openssl_util.cpp ../../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} ${ISAL_CRYPTO_LIBRARIES})
target_link_libraries(test_cluster_client ${OPENSSL_LIBRARIES})
target_compile_definitions(test_cluster_client PUBLIC -D__MOCK__)
target_include_directories(test_cluster_client BEFORE PUBLIC ${CMAKE_SOURCE_DIR}/src/test/mock)
add_dependencies(build_tests test_cluster_client)
+99 -1
View File
@@ -19,7 +19,6 @@
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include "openssl_util.h"
#endif
// libc-ares
@@ -164,6 +163,105 @@ void http_ares_cb(void *data, ares_socket_t socket_fd, int readable, int writabl
});
}
#ifdef WITH_OPENSSL
bool openssl_ctx_add_ca(SSL_CTX *ssl_ctx, const std::string & file_or_pem)
{
std::string pem;
BIO *bio = NULL;
if (file_or_pem.substr(0, 5) != "-----")
{
pem = read_file(file_or_pem);
bio = BIO_new_mem_buf(pem.data(), pem.size());
}
else
bio = BIO_new_mem_buf(file_or_pem.data(), file_or_pem.size());
if (!bio)
return false;
X509 *x509 = PEM_read_bio_X509(bio, NULL, 0, NULL);
bool ok = !!x509;
if (x509)
{
X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx);
X509_STORE_add_cert(store, x509);
X509_free(x509);
}
BIO_free(bio);
return ok;
}
bool openssl_ctx_use_ca(SSL_CTX *ssl_ctx, const std::string & file_or_pem)
{
if (file_or_pem.substr(0, 5) == "-----")
{
return openssl_ctx_add_ca(ssl_ctx, file_or_pem);
}
return file_or_pem.empty()
? !!SSL_CTX_set_default_verify_paths(ssl_ctx)
: !!SSL_CTX_load_verify_locations(ssl_ctx, file_or_pem.c_str(), NULL);
}
std::string openssl_get_cn(X509 *x509)
{
X509_NAME* subj = X509_get_subject_name(x509);
int pos = X509_NAME_get_index_by_NID(subj, NID_commonName, -1);
if (pos != -1)
{
X509_NAME_ENTRY* cn = X509_NAME_get_entry(subj, pos);
ASN1_STRING* str = X509_NAME_ENTRY_get_data(cn);
return std::string((const char*)ASN1_STRING_get0_data(str), ASN1_STRING_length(str));
}
return "";
}
bool openssl_ctx_use_cert(SSL_CTX *ssl_ctx, const std::string & file_or_pem, std::string & common_name)
{
BIO *bio = NULL;
std::string contents;
if (file_or_pem.substr(0, 5) == "-----")
bio = BIO_new_mem_buf(file_or_pem.data(), file_or_pem.size());
else
{
contents = read_file(file_or_pem);
if (!contents.size())
return false;
bio = BIO_new_mem_buf(contents.data(), contents.size());
}
if (!bio)
return false;
X509 *x509 = PEM_read_bio_X509(bio, NULL, 0, NULL);
bool ok = !!x509;
if (x509)
{
ok = SSL_CTX_use_certificate(ssl_ctx, x509);
if (ok)
common_name = openssl_get_cn(x509);
X509_free(x509);
}
BIO_free(bio);
return ok;
}
bool openssl_ctx_use_key(SSL_CTX *ssl_ctx, const std::string & file_or_pem)
{
if (file_or_pem.substr(0, 5) == "-----")
{
BIO *bio = BIO_new_mem_buf(file_or_pem.data(), file_or_pem.size());
if (!bio)
return false;
EVP_PKEY *pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
bool ok = !!pkey;
if (pkey)
{
ok = SSL_CTX_use_PrivateKey(ssl_ctx, pkey);
EVP_PKEY_free(pkey);
}
BIO_free(bio);
return ok;
}
return !!SSL_CTX_use_PrivateKey_file(ssl_ctx, file_or_pem.c_str(), SSL_FILETYPE_PEM);
}
#endif
http_context_t* http_context_init(timerfd_manager_t *tfd, const std::string & ssl_cert, const std::string & ssl_key,
const std::string & ssl_ca, bool verify_peer, std::string & error)
{
+12
View File
@@ -8,6 +8,10 @@
#include <functional>
#include "json11/json11.hpp"
#ifdef WITH_OPENSSL
#include <openssl/types.h>
#endif
#define WS_CONTINUATION 0
#define WS_TEXT 1
#define WS_BINARY 2
@@ -69,3 +73,11 @@ void http_close(http_co_t *co);
void http_destroy(http_co_t *co);
#pragma GCC visibility pop
#ifdef WITH_OPENSSL
bool openssl_ctx_add_ca(SSL_CTX *ssl_ctx, const std::string & file_or_pem);
bool openssl_ctx_use_ca(SSL_CTX *ssl_ctx, const std::string & file_or_pem);
std::string openssl_get_cn(X509 *x509);
bool openssl_ctx_use_cert(SSL_CTX *ssl_ctx, const std::string & file_or_pem, std::string & common_name);
bool openssl_ctx_use_key(SSL_CTX *ssl_ctx, const std::string & file_or_pem);
#endif
+114 -9
View File
@@ -15,6 +15,13 @@
#ifdef WITH_RDMA
#include "msgr_rdma.h"
#endif
#include "http_client.h"
#ifdef WITH_OPENSSL
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#endif
#include <sys/poll.h>
@@ -118,7 +125,50 @@ void msgr_iothread_t::run()
void osd_messenger_t::init()
{
init_tls();
if (!tls_cert.empty() || !tls_key.empty() || !osd_tls_ca.empty() || !client_tls_ca.empty())
{
// 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 (osd_num)
fprintf(stderr, "Vitastor OSD TLS requires osd_tls_cert, osd_tls_key, osd_tls_ca, client_tls_ca\n");
else
fprintf(stderr, "Vitastor client TLS requires tls_cert, tls_key and osd_tls_ca\n");
exit(1);
}
else
{
ssl_ctx = SSL_CTX_new(TLS_method());
if (!ssl_ctx)
{
init_err:
fprintf(stderr, "OpenSSL initialization failed: %s\n", ERR_error_string(ERR_get_error(), NULL));
exit(1);
}
SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
bool ok = SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_3_VERSION);
ok = ok && openssl_ctx_add_ca(ssl_ctx, osd_tls_ca);
if (osd_num)
{
// OSD uses 2 separate root certificates to distinguish between clients and peer OSDs
ok = ok && openssl_ctx_add_ca(ssl_ctx, client_tls_ca);
}
ok = ok && openssl_ctx_use_cert(ssl_ctx, tls_cert, tls_cn);
ok = ok && openssl_ctx_use_key(ssl_ctx, tls_key);
if (!ok)
{
SSL_CTX_free(ssl_ctx);
ssl_ctx = NULL;
goto init_err;
}
}
#endif
}
#ifdef WITH_RDMACM
if (use_rdmacm)
{
@@ -297,15 +347,21 @@ osd_messenger_t::~osd_messenger_t()
rdmacm_evch = NULL;
}
#endif
for (auto encrypt_ctx: encrypt_xts_pool)
for (auto encrypt_ctx: encrypt_ctx_pool)
{
destroy_aes_xts_encrypt(encrypt_ctx);
}
for (auto decrypt_ctx: decrypt_xts_pool)
for (auto decrypt_ctx: decrypt_ctx_pool)
{
destroy_aes_xts_decrypt(decrypt_ctx);
}
destroy_tls();
#ifdef WITH_OPENSSL
if (ssl_ctx)
{
SSL_CTX_free(ssl_ctx);
ssl_ctx = NULL;
}
#endif
}
void osd_messenger_t::parse_config(const json11::Json & config)
@@ -340,9 +396,9 @@ void osd_messenger_t::parse_config(const json11::Json & config)
if (!this->rdma_max_msg || this->rdma_max_msg > 128*1024*1024)
this->rdma_max_msg = 129*1024;
#endif
this->max_cipher_pool_size = config["max_cipher_pool_size"].uint64_value();
if (!this->max_cipher_pool_size)
this->max_cipher_pool_size = 256;
this->max_aes_xts_pool_size = config["max_aes_xts_pool_size"].uint64_value();
if (!this->max_aes_xts_pool_size)
this->max_aes_xts_pool_size = 256;
if (config["proto_checksums"].is_null())
this->use_proto_checksums = MSGR_CSUM_PAYLOAD;
else if (config["proto_checksums"].is_bool())
@@ -364,6 +420,9 @@ void osd_messenger_t::parse_config(const json11::Json & config)
osd_tls_ca = config["osd_tls_ca"].string_value();
client_tls_ca = config["client_tls_ca"].string_value();
}
test_osd_aes_key.resize(32);
if (fromhexstr(config["test_osd_aes_key"].string_value(), 32, (uint8_t*)test_osd_aes_key.data()) != 32)
test_osd_aes_key.clear();
if (!osd_num)
this->iothread_count = (uint32_t)config["client_iothread_count"].uint64_value();
else
@@ -594,7 +653,7 @@ void osd_messenger_t::handle_connect_epoll(int peer_fd)
handle_peer_epoll(peer_fd, epoll_events);
});
// Check OSD number
init_tls_client(cl);
ssl_init(cl, false);
check_peer_config(cl);
}
@@ -836,7 +895,7 @@ void osd_messenger_t::accept_connections(int listen_fd)
cl->peer_fd = peer_fd;
cl->peer_state = PEER_CONNECTED;
cl->in_buf = (uint8_t*)malloc_or_die(receive_buffer_size);
init_tls_client(cl);
ssl_init(cl, true);
// Add FD to epoll
tfd->set_fd_handler(peer_fd, false, [this](int peer_fd, int epoll_events)
{
@@ -851,6 +910,52 @@ void osd_messenger_t::accept_connections(int listen_fd)
}
}
void osd_messenger_t::ssl_init(osd_client_t *cl, bool server_mode)
{
if (!tls_cert.empty())
{
cl->write_to_ssl = BIO_new(BIO_s_mem());
cl->read_from_ssl = BIO_new(BIO_s_mem());
cl->ssl_cli = SSL_new(ssl_ctx);
if (!cl->ssl_cli)
{
fprintf(stderr, "OpenSSL initialization failed: %s\n", ERR_error_string(ERR_get_error(), NULL));
exit(1);
}
if (server_mode)
{
SSL_set_accept_state(cl->ssl_cli);
}
else
{
SSL_set_connect_state(cl->ssl_cli);
}
SSL_set_bio(cl->ssl_cli, cl->write_to_ssl, cl->read_from_ssl);
bool ok = ssl_do_handshake(cl);
assert(ok);
}
else if (!test_osd_aes_key.empty())
{
int r;
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);
}
}
#ifdef WITH_RDMA
msgr_rdma_context_t* osd_messenger_t::choose_rdma_context(osd_client_t *cl)
{
+21 -42
View File
@@ -12,10 +12,8 @@
#include <deque>
#include <vector>
#ifdef WITH_OPENSSL
#include <openssl/types.h>
#ifdef WITH_ISAL_CRYPTO
#include <isa-l_crypto/aes_gcm.h>
#endif
#include "../util/xxh_x86dispatch.h"
@@ -46,9 +44,6 @@
#define DEFAULT_MIN_ZEROCOPY_SEND_SIZE 32*1024
#define AES_256_GCM_KEY_SIZE 32
#define AES_256_GCM_IV_SIZE 12
struct msgr_sendp_t
{
osd_op_t *op;
@@ -95,33 +90,29 @@ struct osd_client_t
msgr_rdma_connection_t *rdma_conn = NULL;
#endif
#ifdef WITH_OPENSSL
SSL *ssl_cli = NULL;
BIO *write_to_ssl = NULL;
// FIXME: use custom bio to avoid 1 more memory copy?
BIO *read_from_ssl = NULL;
uint8_t *ssl_out_buf = NULL;
size_t ssl_out_buf_size = 0, ssl_out_buf_cap = 0;
int ssl_handshake_pending = 0;
bool ssl_handshake_done = false;
msgr_tls_record_hdr_t ssl_read_record;
size_t ssl_read_header_size = 0;
bool ssl_more_to_buffer = false;
bool gcm_enabled = false;
std::vector<uint8_t> my_secret, peer_secret;
std::vector<uint8_t> my_key, peer_key;
uint64_t my_iv_ctr, peer_iv_ctr;
#ifdef WITH_ISAL_CRYPTO
isal_gcm_key_data my_key_isal, peer_key_isal;
isal_gcm_context_data *enc_ctx = NULL;
isal_gcm_context_data *dec_ctx = NULL;
#else
EVP_CIPHER_CTX *enc_ctx = NULL;
EVP_CIPHER_CTX *dec_ctx = NULL;
#endif
uint8_t enc_tag[16];
size_t enc_tag_size = 0;
bool enc_batch = false;
EVP_CIPHER_CTX *dec_ctx = NULL;
uint8_t dec_tag[16];
size_t dec_tag_size = 0;
uint32_t dec_batch_size = 0;
size_t dec_batch_size_size = 0;
std::vector<osd_op_t*> unverified_ops;
#endif
// Read state
bool io_error = false;
@@ -136,7 +127,7 @@ struct osd_client_t
uint64_t read_op_id = 1;
bool check_sequencing = false;
bool enable_pg_locks = false;
op_aes_xts_decrypt_t *xts_dec_ctx = NULL;
op_aes_xts_decrypt_t *decrypt_ctx = NULL;
size_t read_op_inline_decrypt_pos = 0;
size_t read_op_inline_decrypt_in = 0;
int proto_csum_status = 0;
@@ -162,7 +153,7 @@ struct osd_client_t
size_t send_list_size = 0;
std::deque<osd_op_t*> send_free_ops;
std::vector<osd_op_t*> zc_free_list;
op_aes_xts_encrypt_t *xts_enc_ctx = NULL;
op_aes_xts_encrypt_t *encrypt_ctx = NULL;
XXH3_state_t* write_csum_state = NULL;
~osd_client_t();
@@ -267,12 +258,13 @@ protected:
bool use_sync_send_recv = false;
int min_zerocopy_send_size = DEFAULT_MIN_ZEROCOPY_SEND_SIZE;
int iothread_count = 0;
int max_cipher_pool_size = 256;
int max_aes_xts_pool_size = 256;
std::string tls_cert;
std::string tls_key;
std::string osd_tls_ca;
std::string client_tls_ca;
std::string test_osd_aes_key; // FIXME Insecure, only for PoC tests
#ifdef WITH_RDMA
bool use_rdma = true;
@@ -290,19 +282,13 @@ protected:
robin_hood::unordered_flat_map<rdma_cm_id*, rdmacm_connecting_t*> rdmacm_connecting;
#endif
#ifdef WITH_OPENSSL
SSL_CTX *ssl_ctx = NULL;
EVP_KDF_CTX *kdf_ctx = NULL;
X509 *tls_cert_obj = NULL;
X509 *osd_tls_ca_obj = NULL;
X509 *client_tls_ca_obj = NULL;
std::string tls_cn;
void init_tls();
void destroy_tls();
void init_tls_client(osd_client_t *cl);
bool do_tls_handshake(osd_client_t *cl, bool from_recv = false);
bool finalize_tls_handshake(osd_client_t *cl);
bool derive_aes_keys(osd_client_t *cl, bool update_my, bool update_peer);
void ssl_init(osd_client_t *cl, bool server_mode);
bool ssl_do_handshake(osd_client_t *cl);
#endif
std::vector<msgr_iothread_t*> iothreads;
std::vector<uint64_t> read_ready_clients;
@@ -310,16 +296,8 @@ protected:
// 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::vector<op_aes_xts_encrypt_t*> encrypt_xts_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
std::vector<op_aes_xts_encrypt_t*> encrypt_ctx_pool;
std::vector<op_aes_xts_decrypt_t*> decrypt_ctx_pool;
public:
timerfd_manager_t *tfd = NULL;
@@ -397,12 +375,13 @@ protected:
void handle_read(int result, osd_client_t *cl);
bool handle_read_buffer(osd_client_t *cl, uint8_t *curbuf, size_t bufsize);
template<typename T> size_t handle_buffer_with(osd_client_t *cl, uint8_t *curbuf, size_t bufsize);
template<typename T> bool handle_buffer_with(osd_client_t *cl, uint8_t *curbuf, size_t bufsize);
bool handle_hdr(osd_client_t *cl);
bool allocate_op_buffers(osd_client_t *cl);
bool allocate_reply_buffers(osd_client_t *cl, osd_op_t *op);
bool op_read_from(osd_client_t *cl, msgr_op_reader_t & rdr);
bool handle_finished_op(osd_client_t *cl);
void execute_verified_op(osd_client_t *cl, osd_op_t *op);
void handle_immediate_ops();
void 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);
+53 -380
View File
@@ -3,30 +3,13 @@
#include <assert.h>
#ifdef WITH_ISAL_CRYPTO
#include <isa-l_crypto/isal_crypto_api.h>
#endif
#include <mutex>
#include "str_util.h"
#include "etcd_state_client.h"
#include "messenger.h"
#include "msgr_encrypt.h"
#include "http_client.h"
#include "openssl_util.h"
#include <openssl/kdf.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#define MSGR_HSP_HS 1
#define MSGR_HSP_SEND 2
#define MSGR_HSP_RECV 4
op_aes_xts_encrypt_t::op_aes_xts_encrypt_t()
{
#ifndef WITH_ISAL_CRYPTO
#ifdef WITH_OPENSSL
if (!(ctx = EVP_CIPHER_CTX_new()))
{
ERR_print_errors_fp(stderr);
@@ -38,13 +21,16 @@ op_aes_xts_encrypt_t::op_aes_xts_encrypt_t()
ERR_print_errors_fp(stderr);
abort();
}
#else
fprintf(stderr, "Error: Vitastor is built without encryption support\n");
abort();
#endif
}
op_aes_xts_encrypt_t::~op_aes_xts_encrypt_t()
{
assert(!encrypted);
#ifndef WITH_ISAL_CRYPTO
#ifdef WITH_OPENSSL
EVP_CIPHER_CTX_free(ctx);
#endif
if (tmp)
@@ -66,7 +52,7 @@ void op_aes_xts_encrypt_t::start(uint8_t *key, uint64_t start_offset, size_t blo
tmp = NULL;
tmp_size = 0;
}
#ifndef WITH_ISAL_CRYPTO
#ifdef WITH_OPENSSL
if (EVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL) != 1)
{
ERR_print_errors_fp(stderr);
@@ -77,12 +63,9 @@ 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)
{
#ifdef WITH_OPENSSL
uint8_t iv[16] = { 0 };
*((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)
{
ERR_print_errors_fp(stderr);
@@ -115,10 +98,7 @@ void op_aes_xts_encrypt_t::update(uint8_t *in, size_t max_in, uint8_t *out, size
done_out += max_out;
tmp_pos += max_out;
if (tmp_pos >= block_size)
{
encrypted = false;
done_in += 1;
}
}
else if (max_in < block_size - offset%block_size)
{
@@ -146,7 +126,7 @@ void op_aes_xts_encrypt_t::update(uint8_t *in, size_t max_in, uint8_t *out, size
encrypted = true;
memcpy(out, tmp, max_out);
tmp_pos = max_out;
done_in += max_in-1;
done_in += max_in;
offset += max_in;
done_out += max_out;
}
@@ -178,7 +158,7 @@ void destroy_aes_xts_encrypt(op_aes_xts_encrypt_t *encrypt_ctx)
op_aes_xts_decrypt_t::op_aes_xts_decrypt_t()
{
#ifndef WITH_ISAL_CRYPTO
#ifdef WITH_OPENSSL
if (!(ctx = EVP_CIPHER_CTX_new()))
{
ERR_print_errors_fp(stderr);
@@ -190,13 +170,16 @@ op_aes_xts_decrypt_t::op_aes_xts_decrypt_t()
ERR_print_errors_fp(stderr);
abort();
}
#else
fprintf(stderr, "Error: Vitastor is built without encryption support\n");
abort();
#endif
}
op_aes_xts_decrypt_t::~op_aes_xts_decrypt_t()
{
assert(!decrypted);
#ifndef WITH_ISAL_CRYPTO
#ifdef WITH_OPENSSL
EVP_CIPHER_CTX_free(ctx);
#endif
if (tmp)
@@ -207,9 +190,9 @@ void op_aes_xts_decrypt_t::start(uint8_t **key_chain, size_t chain_size, void *k
{
assert(!decrypted);
this->start_offset = start_offset;
this->key_chain = key_chain;
this->chain_size = chain_size;
this->key_indexes = key_indexes;
this->key_chain = chain_size > 1 ? key_chain : 0;
this->chain_size = chain_size > 1 ? chain_size : 0;
this->key_indexes = chain_size > 1 ? key_indexes : NULL;
this->key_index_bytes = osd_op_rw_t::chain_info_bytes(chain_size);
assert(chain_size <= 1 || key_indexes != NULL);
this->block_size = block_size;
@@ -221,7 +204,7 @@ void op_aes_xts_decrypt_t::start(uint8_t **key_chain, size_t chain_size, void *k
tmp = NULL;
tmp_size = 0;
}
#ifndef WITH_ISAL_CRYPTO
#ifdef WITH_OPENSSL
if (chain_size == 1 && key_chain[0] && EVP_DecryptInit_ex(ctx, NULL, NULL, key_chain[0], NULL) != 1)
{
ERR_print_errors_fp(stderr);
@@ -233,7 +216,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)
{
uint8_t *key = NULL;
if (chain_size > 1)
if (chain_size)
{
uint32_t key_index = key_index_bytes == 1
? ((uint8_t*)key_indexes)[offset/block_size]
@@ -244,24 +227,17 @@ void op_aes_xts_decrypt_t::decrypt_block(uint8_t *in, uint8_t *out)
: UINT32_MAX));
assert(key_index < chain_size);
key = key_chain[key_index];
if (!key)
{
if (in != out)
memcpy(out, in, block_size);
return;
}
}
else
{
key = key_chain[0];
}
if (!key)
{
if (in != out)
memcpy(out, in, block_size);
return;
}
#ifdef WITH_OPENSSL
uint8_t iv[16] = { 0 };
*((uint64_t*)iv) = start_offset + offset - offset%block_size;
#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)
if (EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv) != 1)
{
ERR_print_errors_fp(stderr);
abort();
@@ -296,10 +272,7 @@ void op_aes_xts_decrypt_t::update(uint8_t *in, size_t max_in, uint8_t *out, size
done_out += max_out;
tmp_pos += max_out;
if (tmp_pos >= block_size)
{
decrypted = false;
done_in += 1;
}
}
else if (max_in < block_size - offset%block_size)
{
@@ -328,7 +301,7 @@ void op_aes_xts_decrypt_t::update(uint8_t *in, size_t max_in, uint8_t *out, size
if (out)
memcpy(out, tmp, max_out);
tmp_pos = max_out;
done_in += max_in-1;
done_in += max_in;
offset += max_in;
done_out += max_out;
}
@@ -362,23 +335,23 @@ void destroy_aes_xts_decrypt(op_aes_xts_decrypt_t *decrypt_ctx)
void osd_messenger_t::op_encrypted_copy_buf(osd_client_t *cl, uint8_t *enc_buf, size_t enc_len, uint8_t *plain, size_t plain_len, size_t & done_plain, size_t & done_enc)
{
if (!cl->xts_enc_ctx)
if (!cl->encrypt_ctx)
{
if (encrypt_xts_pool.size())
if (encrypt_ctx_pool.size())
{
cl->xts_enc_ctx = encrypt_xts_pool.back();
encrypt_xts_pool.pop_back();
cl->encrypt_ctx = encrypt_ctx_pool.back();
encrypt_ctx_pool.pop_back();
}
else
cl->xts_enc_ctx = new op_aes_xts_encrypt_t();
cl->encrypt_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->encrypt_ctx->start(cl->write_op->enc->key_chain[0], cl->write_op->req.rw.offset, cl->write_op->enc->bitmap_granularity);
}
while (done_plain < plain_len && done_enc < enc_len)
while (done_enc < enc_len && (done_plain < plain_len || cl->encrypt_ctx->has_buffered()))
{
size_t done_in = 0;
size_t done_out = 0;
cl->xts_enc_ctx->update(plain+done_plain, plain_len-done_plain, enc_buf+done_enc, enc_len-done_enc, done_in, done_out);
cl->encrypt_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)
XXH3_64bits_update(cl->write_csum_state, enc_buf+done_enc, done_out);
done_enc += done_out;
@@ -395,7 +368,7 @@ void osd_messenger_t::op_decrypted_copy_buf(osd_client_t *cl, uint8_t *enc_buf,
size_t done_in = 0;
size_t done_out = 0;
// plain == NULL means skip output
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);
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);
if (cl->read_csum_state && done_in > 0)
XXH3_64bits_update(cl->read_csum_state, enc_buf+done_enc, done_in);
done_enc += done_in;
@@ -407,18 +380,18 @@ void osd_messenger_t::op_decrypted_copy_buf(osd_client_t *cl, uint8_t *enc_buf,
void osd_messenger_t::op_decrypt_start(osd_client_t* cl)
{
if (!cl->xts_dec_ctx)
if (!cl->decrypt_ctx)
{
if (decrypt_xts_pool.size())
if (decrypt_ctx_pool.size())
{
cl->xts_dec_ctx = decrypt_xts_pool.back();
decrypt_xts_pool.pop_back();
cl->decrypt_ctx = decrypt_ctx_pool.back();
decrypt_ctx_pool.pop_back();
}
else
cl->xts_dec_ctx = new op_aes_xts_decrypt_t();
cl->decrypt_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->decrypt_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.offset, enc->bitmap_granularity);
}
@@ -450,7 +423,7 @@ void osd_messenger_t::op_decrypt_inline(osd_client_t* cl)
size_t out_len = op->iov.buf[j].iov_len - from_out;
size_t done_in = 0;
size_t done_out = 0;
cl->xts_dec_ctx->update(in, in_len, out, out_len, done_in, done_out);
cl->decrypt_ctx->update(in, in_len, out, out_len, done_in, done_out);
if (done_in >= in_len)
{
i++;
@@ -471,324 +444,24 @@ void osd_messenger_t::op_decrypt_inline(osd_client_t* cl)
void osd_messenger_t::op_decrypt_free(osd_client_t* cl)
{
if (cl->xts_dec_ctx)
if (cl->decrypt_ctx)
{
if (decrypt_xts_pool.size() > max_cipher_pool_size)
delete cl->xts_dec_ctx;
if (decrypt_ctx_pool.size() > max_aes_xts_pool_size)
delete cl->decrypt_ctx;
else
decrypt_xts_pool.push_back(cl->xts_dec_ctx);
cl->xts_dec_ctx = NULL;
decrypt_ctx_pool.push_back(cl->decrypt_ctx);
cl->decrypt_ctx = NULL;
}
}
void osd_messenger_t::op_encrypt_free(osd_client_t* cl)
{
if (cl->xts_enc_ctx)
if (cl->encrypt_ctx)
{
if (encrypt_xts_pool.size() > max_cipher_pool_size)
delete cl->xts_enc_ctx;
if (encrypt_ctx_pool.size() > max_aes_xts_pool_size)
delete cl->encrypt_ctx;
else
encrypt_xts_pool.push_back(cl->xts_enc_ctx);
cl->xts_enc_ctx = NULL;
}
}
struct tls_secrets_t
{
std::vector<uint8_t> client_secret;
std::vector<uint8_t> server_secret;
};
// Sadly we have to use a global variable to capture TLS 1.3 secrets
static std::mutex logged_secrets_mu;
static std::map<const SSL*, tls_secrets_t> logged_secrets;
static void openssl_key_log(const SSL *ssl, const char *line)
{
// Format: <CLIENT|SERVER>_TRAFFIC_SECRET_0 <server_random> <secret>
bool is_client_secret = !strncmp(line, "CLIENT_TRAFFIC_SECRET_0 ", strlen("CLIENT_TRAFFIC_SECRET_0 "));
bool is_server_secret = !strncmp(line, "SERVER_TRAFFIC_SECRET_0 ", strlen("SERVER_TRAFFIC_SECRET_0 "));
if (!is_client_secret && !is_server_secret)
return;
const char *hex = strchr(line+strlen("CLIENT_TRAFFIC_SECRET_0 "), ' ');
if (!hex)
return;
hex++;
size_t len = strlen(hex);
logged_secrets_mu.lock();
auto & secrets = logged_secrets[ssl];
logged_secrets_mu.unlock();
auto & secret = is_client_secret ? secrets.client_secret : secrets.server_secret;
secret.resize(len/2);
fromhexstr(hex, len, secret.data(), secret.size());
}
static bool derive_kdf(EVP_KDF_CTX* kdf_ctx, const uint8_t* insecret, size_t insecret_len,
const uint8_t* salt, size_t salt_len, const char *label, uint8_t *key, size_t size)
{
OSSL_PARAM params[5];
int n = 0;
params[n++] = OSSL_PARAM_construct_utf8_string("digest", (char*)"sha384", (size_t)7);
params[n++] = OSSL_PARAM_construct_octet_string("key", (void*)insecret, insecret_len);
params[n++] = OSSL_PARAM_construct_octet_string("info", (void*)label, strlen(label)+1);
if (salt)
params[n++] = OSSL_PARAM_construct_octet_string("salt", (void*)salt, salt_len);
params[n++] = OSSL_PARAM_construct_end();
assert(n <= sizeof(params)/sizeof(OSSL_PARAM));
if (EVP_KDF_CTX_set_params(kdf_ctx, params) <= 0)
{
ERR_print_errors_fp(stderr);
return false;
}
if (EVP_KDF_derive(kdf_ctx, key, size, NULL) <= 0)
{
ERR_print_errors_fp(stderr);
return false;
}
return true;
}
bool osd_messenger_t::derive_aes_keys(osd_client_t *cl, bool update_my, bool update_peer)
{
std::vector<uint8_t> old_my = cl->my_key, old_peer = cl->peer_key;
if (!cl->my_secret.size() || !cl->peer_secret.size())
{
assert(cl->ssl_cli);
logged_secrets_mu.lock();
auto & secrets = logged_secrets[cl->ssl_cli];
cl->my_secret = std::move(cl->is_incoming ? secrets.client_secret : secrets.server_secret);
cl->peer_secret = std::move(!cl->is_incoming ? secrets.client_secret : secrets.server_secret);
logged_secrets.erase(cl->ssl_cli);
logged_secrets_mu.unlock();
SSL_free(cl->ssl_cli);
cl->ssl_cli = NULL;
cl->gcm_enabled = true;
cl->write_to_ssl = NULL;
cl->read_from_ssl = NULL;
if (cl->my_secret.size() < 32 || cl->peer_secret.size() < 32)
{
fprintf(stderr, "Client %ju error: failed to capture TLS handshake results\n", cl->client_id);
return false;
}
}
// Both keys include AES key and iv + xxhash3 secret
const auto len = AES_256_GCM_KEY_SIZE + AES_256_GCM_IV_SIZE + XXH_SECRET_DEFAULT_SIZE;
cl->my_key.resize(len);
cl->peer_key.resize(len);
bool ok = true;
if (update_my || !old_my.size())
{
ok = ok && derive_kdf(kdf_ctx, cl->my_secret.data(), cl->my_secret.size(),
old_my.size() ? old_my.data() : NULL, old_my.size(),
cl->is_incoming ? "server key" : "client key",
cl->my_key.data(), len);
#ifdef WITH_ISAL_CRYPTO
if (ok)
isal_aes_gcm_pre_256(cl->my_key.data(), &cl->my_key_isal);
#endif
cl->my_iv_ctr = 0;
}
if (update_peer || !old_peer.size())
{
ok = ok && derive_kdf(kdf_ctx, cl->peer_secret.data(), cl->peer_secret.size(),
old_peer.size() ? old_peer.data() : NULL, old_peer.size(),
!cl->is_incoming ? "server key" : "client key",
cl->peer_key.data(), len);
#ifdef WITH_ISAL_CRYPTO
if (ok)
isal_aes_gcm_pre_256(cl->peer_key.data(), &cl->peer_key_isal);
#endif
cl->peer_iv_ctr = 0;
}
return ok;
}
void osd_messenger_t::init_tls()
{
if (!tls_cert.empty() || !tls_key.empty() || !osd_tls_ca.empty() || !client_tls_ca.empty())
{
// Initialize TLS context
if (tls_cert.empty() || tls_key.empty() || osd_tls_ca.empty() || osd_num && client_tls_ca.empty())
{
if (osd_num)
fprintf(stderr, "Vitastor OSD TLS requires osd_tls_cert, osd_tls_key, osd_tls_ca, client_tls_ca\n");
else
fprintf(stderr, "Vitastor client TLS requires tls_cert, tls_key and osd_tls_ca\n");
exit(1);
}
else
{
ssl_ctx = SSL_CTX_new(TLS_method());
if (!ssl_ctx)
{
init_err:
fprintf(stderr, "OpenSSL initialization failed: %s\n", ERR_error_string(ERR_get_error(), NULL));
exit(1);
}
// Always use TLS 1.3 with AES-256-GCM
SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_3_VERSION);
SSL_CTX_set_max_proto_version(ssl_ctx, TLS1_3_VERSION);
SSL_CTX_set_ciphersuites(ssl_ctx, "TLS_AES_256_GCM_SHA384");
SSL_CTX_set_keylog_callback(ssl_ctx, openssl_key_log);
SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
bool ok = SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_3_VERSION);
ok = ok && (osd_tls_ca_obj = openssl_load_cert(osd_tls_ca));
ok = ok && X509_STORE_add_cert(SSL_CTX_get_cert_store(ssl_ctx), osd_tls_ca_obj);
if (osd_num)
{
// OSD uses 2 separate root certificates to distinguish between clients and peer OSDs
ok = ok && (client_tls_ca_obj = openssl_load_cert(client_tls_ca));
ok = ok && X509_STORE_add_cert(SSL_CTX_get_cert_store(ssl_ctx), client_tls_ca_obj);
}
ok = ok && openssl_ctx_use_cert(ssl_ctx, tls_cert, tls_cn);
ok = ok && openssl_ctx_use_key(ssl_ctx, tls_key);
EVP_KDF *kdf;
ok = ok && (kdf = EVP_KDF_fetch(NULL, "hkdf", NULL));
ok = ok && (kdf_ctx = EVP_KDF_CTX_new(kdf));
if (kdf)
EVP_KDF_free(kdf);
if (!ok)
{
SSL_CTX_free(ssl_ctx);
ssl_ctx = NULL;
goto init_err;
}
}
}
}
void osd_messenger_t::init_tls_client(osd_client_t *cl)
{
if (!tls_cert.empty())
{
cl->write_to_ssl = BIO_new(BIO_s_mem());
cl->read_from_ssl = BIO_new(BIO_s_mem());
cl->ssl_cli = SSL_new(ssl_ctx);
cl->ssl_handshake_pending = MSGR_HSP_HS;
if (!cl->ssl_cli)
{
fprintf(stderr, "OpenSSL initialization failed: %s\n", ERR_error_string(ERR_get_error(), NULL));
exit(1);
}
if (cl->is_incoming)
{
SSL_set_accept_state(cl->ssl_cli);
}
else
{
SSL_set_connect_state(cl->ssl_cli);
}
SSL_set_bio(cl->ssl_cli, cl->write_to_ssl, cl->read_from_ssl);
bool ok = do_tls_handshake(cl);
assert(ok);
}
}
bool osd_messenger_t::do_tls_handshake(osd_client_t *cl, bool from_recv)
{
if (!(cl->ssl_handshake_pending & MSGR_HSP_HS))
return true;
int r = SSL_do_handshake(cl->ssl_cli);
if (r > 0)
{
// Server-side OpenSSL treats handshake as finalized only when receiving
// the first message, so we transmit 1 byte after connecting and only then
// finalize the handshake
cl->ssl_handshake_pending = MSGR_HSP_SEND|MSGR_HSP_RECV;
if (cl->write_state == 0 && from_recv)
{
cl->write_state = CL_WRITE_READY;
write_ready_clients.push_back(cl->client_id);
}
}
else
{
r = SSL_get_error(cl->ssl_cli, r);
if (r != 0 && r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE)
{
fprintf(stderr, "Client %ju TLS handshake error: %s, stopping client\n", cl->client_id, ERR_error_string(ERR_get_error(), NULL));
cl->io_error = true;
return false;
}
if (from_recv && cl->write_state == 0 && openssl_bio_nonempty(cl->read_from_ssl))
{
cl->write_state = CL_WRITE_READY;
write_ready_clients.push_back(cl->client_id);
}
}
return true;
}
bool osd_messenger_t::finalize_tls_handshake(osd_client_t *cl)
{
if (cl->ssl_handshake_pending)
return true;
// Capture secrets and switch to direct AES-256-GCM encryption
if (!derive_aes_keys(cl, true, true))
{
cl->io_error = true;
return false;
}
if (cl->read_op)
{
assert(!cl->read_op_pos);
delete cl->read_op;
cl->read_op = NULL;
}
if (cl->write_op)
{
assert(!cl->write_op_pos);
cl->write_ops.insert(cl->write_ops.begin(), cl->write_op);
cl->write_op = NULL;
}
if (cl->write_state == 0)
{
cl->write_state = CL_WRITE_READY;
write_ready_clients.push_back(cl->client_id);
}
// Switched to direct AES-GCM, stop SSL callers
return false;
}
void osd_messenger_t::destroy_tls()
{
#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 (osd_tls_ca_obj)
{
X509_free(osd_tls_ca_obj);
osd_tls_ca_obj = NULL;
}
if (client_tls_ca_obj)
{
X509_free(client_tls_ca_obj);
client_tls_ca_obj = NULL;
}
if (ssl_ctx)
{
SSL_CTX_free(ssl_ctx);
ssl_ctx = NULL;
}
if (kdf_ctx)
{
EVP_KDF_CTX_free(kdf_ctx);
kdf_ctx = NULL;
encrypt_ctx_pool.push_back(cl->encrypt_ctx);
cl->encrypt_ctx = NULL;
}
}
+7 -6
View File
@@ -3,18 +3,17 @@
#include <stdint.h>
#ifdef WITH_ISAL_CRYPTO
#include <isa-l_crypto/aes_xts.h>
#endif
#include "../util/xxh_x86dispatch.h"
// WITH_OPENSSL is left to possibly support other crypto libraries
#ifdef WITH_OPENSSL
#include <openssl/conf.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#endif
class op_aes_xts_encrypt_t
{
#ifndef WITH_ISAL_CRYPTO
#ifdef WITH_OPENSSL
EVP_CIPHER_CTX *ctx = NULL;
#endif
uint64_t start_offset = 0;
@@ -32,6 +31,7 @@ public:
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 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
{
#ifndef WITH_ISAL_CRYPTO
#ifdef WITH_OPENSSL
EVP_CIPHER_CTX *ctx = NULL;
#endif
uint64_t start_offset = 0;
@@ -61,6 +61,7 @@ public:
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 update(uint8_t *in, size_t max_in, uint8_t *out, size_t max_out, size_t & done_in, size_t & done_out);
};
+4 -1
View File
@@ -8,7 +8,6 @@
osd_op_t::~osd_op_t()
{
assert(!bs_op);
assert(!op_data);
if (bitmap_buf)
{
free(bitmap_buf);
@@ -27,6 +26,10 @@ osd_op_t::~osd_op_t()
{
free(enc_buf);
}
if (op_data)
{
free(op_data);
}
}
bool osd_op_t::is_recovery_related()
+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)
{
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)
dst_len = rc->max_msg;
copied = copy_ops_to(cl, dst, dst_len);
-4
View File
@@ -19,7 +19,6 @@ struct rdmacm_connecting_t
int tcp_port = 0;
int timeout_ms = 0;
int timeout_id = -1;
bool is_incoming = false;
msgr_rdma_context_t *rdma_context = NULL;
};
@@ -293,7 +292,6 @@ void osd_messenger_t::rdmacm_accept(rdma_cm_event *ev)
conn->client_id = next_client_id++;
conn->parsed_addr = *(sockaddr_storage*)rdma_get_peer_addr(ev->id);
conn->rdma_context = rdma_context;
conn->is_incoming = true;
rdmacm_set_conn_timeout(conn);
rdmacm_connecting[ev->id] = conn;
fprintf(stderr, "[OSD %ju] new client %ju: connection from %s via RDMA-CM\n", this->osd_num, conn->client_id,
@@ -494,13 +492,11 @@ void osd_messenger_t::rdmacm_established(rdma_cm_event *ev)
cl->peer_addr = conn->parsed_addr;
cl->peer_port = conn->rdmacm_port;
cl->client_id = conn->client_id;
cl->is_incoming = conn->is_incoming;
cl->peer_state = PEER_RDMA;
cl->connect_timeout_id = -1;
cl->osd_num = peer_osd;
cl->in_buf = (uint8_t*)malloc_or_die(receive_buffer_size);
cl->rdma_conn = rc;
init_tls_client(cl);
clients[conn->client_id] = cl;
if (conn->timeout_id >= 0)
{
+133 -179
View File
@@ -4,21 +4,18 @@
#define _XOPEN_SOURCE
#include <limits.h>
#include "messenger.h"
#include "openssl_util.h"
#ifdef WITH_OPENSSL
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#endif
#define RDR_GCM 1
#define RDR_TLS 1
#define RDR_XTS 2
#define RDR_NO_CSUM 4
#define MSGR_HSP_HS 1
#define MSGR_HSP_SEND 2
#define MSGR_HSP_RECV 4
class msgr_op_reader_t
{
public:
@@ -104,30 +101,6 @@ class ssl_op_reader_t: public msgr_op_reader_t
size_t bufsize;
size_t done;
bool read_ssl(void *buf, size_t & len)
{
int ok = SSL_read_ex(cl->ssl_cli, buf, len, &len);
if (ok > 0)
{
return true;
}
len = 0;
ok = SSL_get_error(cl->ssl_cli, ok);
if (ok == SSL_ERROR_ZERO_RETURN)
{
fprintf(stderr, "Client %ju TLS disconnected\n", cl->client_id);
cl->io_error = true;
return false;
}
else if (ok != 0 && ok != SSL_ERROR_WANT_WRITE && ok != SSL_ERROR_WANT_READ)
{
fprintf(stderr, "Client %ju TLS read error: %s. Disconnecting client\n", cl->client_id, ERR_error_string(ERR_get_error(), NULL));
cl->io_error = true;
return false;
}
return true;
}
public:
ssl_op_reader_t(osd_messenger_t* msgr, osd_client_t* cl, uint8_t *curbuf, size_t bufsize):
msgr(msgr), cl(cl), from(cl->read_op_pos), curbuf(curbuf), bufsize(bufsize), done(0)
@@ -195,7 +168,7 @@ public:
if (done >= bufsize)
return false;
size_t n = dst_len-from;
if (!(flags & RDR_GCM) || !cl->ssl_cli)
if (!(flags & RDR_TLS) || !cl->ssl_cli)
{
if (n > bufsize-done)
n = bufsize-done;
@@ -229,31 +202,42 @@ public:
assert(dst != NULL);
buffer_again:
buffer_encrypted();
if (cl->ssl_handshake_pending)
if (!cl->ssl_handshake_done)
{
if (!msgr->do_tls_handshake(cl, true))
if (!msgr->ssl_do_handshake(cl))
return false;
if (cl->ssl_handshake_pending & MSGR_HSP_RECV)
if (cl->write_state == 0)
{
uint8_t first_byte = 0;
size_t b = 1;
if (!read_ssl(&first_byte, b))
return false;
if (!b)
// SSL_ERROR_WANT_WRITE is absolutely non-informative with memory BIO, it basically never happens
// So we have to check memory BIO for outstanding data
char *bio_buf = NULL;
size_t bio_sz = BIO_get_mem_data(cl->read_from_ssl, &bio_buf);
if (bio_sz > 0)
{
if (done < bufsize)
goto buffer_again;
return false;
cl->write_state = CL_WRITE_READY;
msgr->write_ready_clients.push_back(cl->client_id);
}
cl->ssl_handshake_pending &= ~MSGR_HSP_RECV;
if (!msgr->finalize_tls_handshake(cl))
return false;
}
}
if (!read_ssl(dst+from, n))
int ok = SSL_read_ex(cl->ssl_cli, dst+from, n, &n);
if (!ok)
{
if (done < bufsize)
goto buffer_again;
ok = SSL_get_error(cl->ssl_cli, ok);
if (ok == SSL_ERROR_WANT_READ)
{
if (done < bufsize)
goto buffer_again;
}
else if (ok == SSL_ERROR_ZERO_RETURN)
{
fprintf(stderr, "Client %ju TLS disconnected\n", cl->client_id);
cl->io_error = true;
}
else if (ok != 0 && ok != SSL_ERROR_WANT_WRITE)
{
fprintf(stderr, "Client %ju TLS read error: %s. Disconnecting client\n", cl->client_id, ERR_error_string(ERR_get_error(), NULL));
cl->io_error = true;
}
return false;
}
if (cl->read_csum_state && !(flags & RDR_NO_CSUM))
@@ -303,49 +287,6 @@ public:
void reset()
{
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
}
}
#ifdef WITH_ISAL_CRYPTO
int r = isal_aes_gcm_init_256(&cl->peer_key_isal, cl->dec_ctx, cl->peer_key.data() + AES_256_GCM_KEY_SIZE, 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, cl->peer_key.data(), cl->peer_key.data() + AES_256_GCM_KEY_SIZE);
if (r != 1)
{
fprintf(stderr, "DecryptInit error: ");
ERR_print_errors_fp(stderr);
abort();
}
#endif
// Increase IV
cl->peer_iv_ctr++;
(*(uint64_t*)(cl->peer_key.data() + AES_256_GCM_KEY_SIZE))++;
}
bool read(uint8_t *dst, size_t dst_len, int flags) override
@@ -359,7 +300,7 @@ public:
if (done >= bufsize)
return false;
size_t n = dst_len-from;
if (!(flags & RDR_GCM))
if (!(flags & RDR_TLS))
{
if (n > bufsize-done)
n = bufsize-done;
@@ -391,13 +332,34 @@ public:
{
// Here, dst == NULL is not allowed
assert(dst != NULL);
if (cl->dec_batch_size_size < 4)
{
size_t n = 4-cl->dec_batch_size_size;
if (n > bufsize-done)
n = bufsize-done;
memcpy(&cl->dec_batch_size, curbuf+done, n);
cl->dec_batch_size_size += n;
done += n;
if (cl->dec_batch_size_size < 4)
return false;
if (!cl->dec_batch_size)
{
fprintf(stderr, "Client %ju - empty batch received, disconnecting\n", cl->client_id);
cl->io_error = true;
return false;
}
uint8_t iv[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
int r = EVP_DecryptInit_ex(cl->dec_ctx, NULL, NULL, (uint8_t*)msgr->test_osd_aes_key.data(), iv);
if (r != 1)
{
fprintf(stderr, "DecryptInit error: ");
ERR_print_errors_fp(stderr);
abort();
}
}
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);
#else
int actual_out;
if (EVP_DecryptUpdate(cl->dec_ctx, dst+from, &actual_out, curbuf+done, n) != 1)
{
@@ -406,7 +368,6 @@ public:
abort();
}
assert(actual_out == n);
#endif
if (cl->read_csum_state && !(flags & RDR_NO_CSUM))
{
XXH3_64bits_update(cl->read_csum_state, dst+from, n);
@@ -425,6 +386,12 @@ public:
bool finish() override
{
if (cl->dec_batch_size > 1)
{
// No tag yet
cl->dec_batch_size--;
return true;
}
if (cl->dec_tag_size+bufsize-done < 16)
{
// Buffer part of the tag
@@ -433,62 +400,33 @@ public:
done = bufsize;
return false;
}
#ifdef WITH_ISAL_CRYPTO
uint8_t calc_tag[16];
int r = isal_aes_gcm_dec_256_finalize(&cl->peer_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;
if (cl->dec_tag_size > 0)
{
// 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);
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;
r = EVP_CIPHER_CTX_ctrl(cl->dec_ctx, EVP_CTRL_GCM_SET_TAG, 16, cl->dec_tag);
}
else
{
// Take full tag directly from the source buffer
r = EVP_CIPHER_CTX_ctrl(cl->dec_ctx, EVP_CTRL_GCM_SET_TAG, 16, curbuf+done);
assert(r == 1);
done += 16;
}
assert(r == 1);
int len = 0;
r = EVP_DecryptFinal_ex(cl->dec_ctx, NULL, &len);
assert(len == 0);
#endif
if (r != 1)
{
fprintf(stderr, "Client %ju AES-GCM decryption failed\n", cl->client_id);
cl->io_error = true;
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;
assert(len == 0);
cl->dec_batch_size = 0;
cl->dec_batch_size_size = 0;
return true;
}
@@ -548,15 +486,17 @@ public:
bool read(uint8_t *dst, size_t dst_len, int flags) override
{
if (cl->dec_ctx)
return false; // FIXME Only for tests, use copy-only with AES
if (from >= dst_len)
{
// Skip
from -= dst_len;
return true;
}
if ((flags & RDR_GCM) && (cl->ssl_cli || cl->gcm_enabled))
if ((flags & RDR_TLS) && cl->ssl_cli)
{
// Can't inplace read TLS/GCM data
// Can't inplace read TLS data
return false;
}
if (cl->recv_list.size() >= IOV_MAX)
@@ -580,7 +520,7 @@ public:
bool finish() override
{
if (cl->gcm_enabled)
if (cl->dec_ctx)
return false;
return true;
}
@@ -736,6 +676,8 @@ out_wakeup:
{
goto out_wakeup;
}
execute_verified_op(cl, cl->read_op);
cl->read_op = NULL;
}
}
cl->read_msg.msg_iovlen = 0;
@@ -776,29 +718,15 @@ void osd_messenger_t::handle_immediate_ops()
bool osd_messenger_t::handle_read_buffer(osd_client_t *cl, uint8_t *curbuf, size_t bufsize)
{
size_t done;
if (cl->ssl_cli)
if (cl->dec_ctx)
{
done = handle_buffer_with<ssl_op_reader_t>(cl, curbuf, bufsize);
if (done > 0 && done < bufsize && !cl->ssl_cli && cl->gcm_enabled)
{
done += handle_buffer_with<gcm_op_reader_t>(cl, curbuf+done, bufsize-done);
}
return handle_buffer_with<gcm_op_reader_t>(cl, curbuf, bufsize);
}
else if (cl->gcm_enabled)
{
done = handle_buffer_with<gcm_op_reader_t>(cl, curbuf, bufsize);
}
else
{
done = handle_buffer_with<copy_op_reader_t>(cl, curbuf, bufsize);
}
assert(!done || done == bufsize);
return !!done;
return handle_buffer_with<copy_op_reader_t>(cl, curbuf, bufsize);
}
template<typename T>
size_t osd_messenger_t::handle_buffer_with(osd_client_t *cl, uint8_t *curbuf, size_t bufsize)
bool osd_messenger_t::handle_buffer_with(osd_client_t *cl, uint8_t *curbuf, size_t bufsize)
{
T rdr(this, cl, curbuf, bufsize);
// Reset OSD ping state
@@ -822,22 +750,42 @@ size_t osd_messenger_t::handle_buffer_with(osd_client_t *cl, uint8_t *curbuf, si
{
if (!cl->read_csum_state)
cl->read_csum_state = XXH3_createState();
if (cl->peer_key.size() == AES_256_GCM_KEY_SIZE + AES_256_GCM_IV_SIZE + XXH_SECRET_DEFAULT_SIZE)
XXH3_64bits_reset_withSecret(cl->read_csum_state, cl->peer_key.data() + AES_256_GCM_KEY_SIZE + AES_256_GCM_IV_SIZE, XXH_SECRET_DEFAULT_SIZE);
else
XXH3_64bits_reset(cl->read_csum_state);
XXH3_64bits_reset(cl->read_csum_state);
}
if (!op_read_from(cl, rdr) || !handle_finished_op(cl))
{
if (cl->io_error)
{
stop_client(cl->client_id);
return 0;
return false;
}
break;
}
if constexpr (std::is_same_v<T, gcm_op_reader_t>)
{
if (cl->dec_batch_size_size)
{
// Operation is not verified yet
cl->unverified_ops.push_back(cl->read_op);
}
else
{
for (auto & op: cl->unverified_ops)
{
execute_verified_op(cl, op);
}
cl->unverified_ops.clear();
execute_verified_op(cl, cl->read_op);
}
}
else
{
execute_verified_op(cl, cl->read_op);
}
cl->read_op = NULL;
}
return rdr.get_done();
assert(rdr.get_done() == bufsize);
return true;
}
bool osd_messenger_t::handle_hdr(osd_client_t *cl)
@@ -1016,7 +964,7 @@ bool osd_messenger_t::op_read_from(osd_client_t *cl, msgr_op_reader_t & rdr)
bool hdr = (cl->read_op_pos < OSD_PACKET_SIZE);
if (hdr || op->op_type == OSD_OP_IN)
{
if (!rdr.read(op->req.buf, OSD_PACKET_SIZE, RDR_GCM | (cl->proto_csum_status == MSGR_CSUM_PAYLOAD ? RDR_NO_CSUM : 0)))
if (!rdr.read(op->req.buf, OSD_PACKET_SIZE, RDR_TLS | (cl->proto_csum_status == MSGR_CSUM_PAYLOAD ? RDR_NO_CSUM : 0)))
return false;
if (hdr)
{
@@ -1032,7 +980,7 @@ bool osd_messenger_t::op_read_from(osd_client_t *cl, msgr_op_reader_t & rdr)
if (op->req.hdr.opcode == OSD_OP_SEC_WRITE ||
op->req.hdr.opcode == OSD_OP_SEC_WRITE_STABLE)
{
if (!rdr.read((uint8_t*)op->bitmap, op->req.sec_rw.attr_len, RDR_GCM))
if (!rdr.read((uint8_t*)op->bitmap, op->req.sec_rw.attr_len, RDR_TLS))
return false;
if (!rdr.read((uint8_t*)op->buf, op->req.sec_rw.len, 0))
return false;
@@ -1040,12 +988,12 @@ bool osd_messenger_t::op_read_from(osd_client_t *cl, msgr_op_reader_t & rdr)
else if (op->req.hdr.opcode == OSD_OP_SEC_STABILIZE ||
op->req.hdr.opcode == OSD_OP_SEC_ROLLBACK)
{
if (!rdr.read((uint8_t*)op->buf, op->req.sec_stab.len, RDR_GCM))
if (!rdr.read((uint8_t*)op->buf, op->req.sec_stab.len, RDR_TLS))
return false;
}
else if (op->req.hdr.opcode == OSD_OP_SEC_READ_BMP)
{
if (!rdr.read((uint8_t*)op->buf, op->req.sec_read_bmp.len, RDR_GCM))
if (!rdr.read((uint8_t*)op->buf, op->req.sec_read_bmp.len, RDR_TLS))
return false;
}
else if (op->req.hdr.opcode == OSD_OP_WRITE)
@@ -1055,20 +1003,20 @@ bool osd_messenger_t::op_read_from(osd_client_t *cl, msgr_op_reader_t & rdr)
}
else if (op->req.hdr.opcode == OSD_OP_SHOW_CONFIG)
{
if (!rdr.read((uint8_t*)op->buf, op->req.show_conf.json_len, RDR_GCM))
if (!rdr.read((uint8_t*)op->buf, op->req.show_conf.json_len, RDR_TLS))
return false;
}
}
else
{
if (!rdr.read(op->reply.buf, OSD_PACKET_SIZE, RDR_GCM | (cl->proto_csum_status == MSGR_CSUM_PAYLOAD ? RDR_NO_CSUM : 0)))
if (!rdr.read(op->reply.buf, OSD_PACKET_SIZE, RDR_TLS | (cl->proto_csum_status == MSGR_CSUM_PAYLOAD ? RDR_NO_CSUM : 0)))
return false;
switched_type:
if (op->reply.hdr.opcode == OSD_OP_SEC_READ)
{
if (op->reply.sec_rw.attr_len > 0)
{
if (!rdr.read((uint8_t*)op->bitmap, op->reply.sec_rw.attr_len, RDR_GCM))
if (!rdr.read((uint8_t*)op->bitmap, op->reply.sec_rw.attr_len, RDR_TLS))
return false;
}
if (op->reply.hdr.retval > 0)
@@ -1082,7 +1030,7 @@ switched_type:
{
if (op->reply.rw.bitmap_len > 0)
{
if (!rdr.read((uint8_t*)op->bitmap, op->reply.rw.bitmap_len, RDR_GCM))
if (!rdr.read((uint8_t*)op->bitmap, op->reply.rw.bitmap_len, RDR_TLS))
return false;
}
if (op->reply.hdr.retval > 0)
@@ -1094,25 +1042,25 @@ switched_type:
}
else if (op->reply.hdr.opcode == OSD_OP_SEC_LIST && op->reply.hdr.retval > 0)
{
if (!rdr.read((uint8_t*)op->buf, sizeof(obj_ver_id) * op->reply.hdr.retval, RDR_GCM))
if (!rdr.read((uint8_t*)op->buf, sizeof(obj_ver_id) * op->reply.hdr.retval, RDR_TLS))
return false;
}
else if ((op->reply.hdr.opcode == OSD_OP_SEC_READ_BMP ||
op->reply.hdr.opcode == OSD_OP_SHOW_CONFIG) && op->reply.hdr.retval > 0)
{
if (!rdr.read((uint8_t*)op->buf, op->reply.hdr.retval, RDR_GCM))
if (!rdr.read((uint8_t*)op->buf, op->reply.hdr.retval, RDR_TLS))
return false;
}
else if (op->reply.hdr.opcode == OSD_OP_DESCRIBE && op->reply.describe.result_bytes > 0)
{
if (!rdr.read((uint8_t*)op->buf, op->reply.describe.result_bytes, RDR_GCM))
if (!rdr.read((uint8_t*)op->buf, op->reply.describe.result_bytes, RDR_TLS))
return false;
}
}
if (cl->proto_csum_status == MSGR_CSUM_FULL ||
cl->read_op_size > 0 && cl->proto_csum_status == MSGR_CSUM_PAYLOAD)
{
if (!rdr.read((uint8_t*)&op->csum, 8, RDR_GCM|RDR_NO_CSUM))
if (!rdr.read((uint8_t*)&op->csum, 8, RDR_TLS|RDR_NO_CSUM))
return false;
}
if (!rdr.finish())
@@ -1140,12 +1088,7 @@ bool osd_messenger_t::handle_finished_op(osd_client_t *cl)
return false;
}
}
if (op->op_type == OSD_OP_IN)
{
// Operation is ready
cl->received_ops.push_back(op);
}
else
if (op->op_type == OSD_OP_OUT)
{
// Inline decryption
if (cl->read_op_inline_decrypt_pos != (size_t)-1)
@@ -1153,6 +1096,20 @@ bool osd_messenger_t::handle_finished_op(osd_client_t *cl)
op_decrypt_inline(cl);
cl->read_op_inline_decrypt_pos = (size_t)-1;
}
}
op_decrypt_free(cl);
return true;
}
void osd_messenger_t::execute_verified_op(osd_client_t *cl, osd_op_t *op)
{
if (op->op_type == OSD_OP_IN)
{
// Operation is ready
cl->received_ops.push_back(op);
}
else
{
// Measure subop (outbound op) latency
timespec tv_end;
clock_gettime(CLOCK_REALTIME, &tv_end);
@@ -1167,8 +1124,5 @@ bool osd_messenger_t::handle_finished_op(osd_client_t *cl)
(tv_end.tv_nsec - op->tv_begin.tv_nsec)/1000
);
}
op_decrypt_free(cl);
set_immediate_ops.push_back(op);
cl->read_op = NULL;
return true;
}
+212 -256
View File
@@ -7,19 +7,17 @@
#include "messenger.h"
#ifdef WITH_OPENSSL
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#endif
#define WR_GCM 1
#define WR_TLS 1
#define WR_XTS 2
#define WR_NO_CSUM 4
#define MSGR_HSP_HS 1
#define MSGR_HSP_SEND 2
#define MSGR_HSP_RECV 4
class msgr_op_writer_t
{
public:
@@ -39,8 +37,6 @@ protected:
size_t done;
public:
constexpr static bool is_ssl = false;
copy_op_writer_t(osd_messenger_t* msgr, osd_client_t* cl, uint8_t *curbuf, size_t bufsize):
msgr(msgr), cl(cl), from(cl->write_op_pos), curbuf(curbuf), bufsize(bufsize), done(0)
{}
@@ -101,8 +97,6 @@ class ssl_op_writer_t: public msgr_op_writer_t
size_t done;
public:
constexpr static bool is_ssl = true;
ssl_op_writer_t(osd_messenger_t* msgr, osd_client_t* cl, uint8_t *curbuf, size_t bufsize):
msgr(msgr), cl(cl), from(cl->write_op_pos), curbuf(curbuf), bufsize(bufsize), done(0)
{
@@ -113,29 +107,14 @@ public:
from = cl->write_op_pos;
}
bool flush_ssl()
void flush_ssl()
{
if (cl->ssl_handshake_pending)
if (!cl->ssl_handshake_done)
{
if (!msgr->do_tls_handshake(cl))
return false;
if (cl->ssl_handshake_pending & MSGR_HSP_SEND)
{
uint8_t first_byte = 0;
size_t f = 0;
if (!write_to_ssl(cl, &first_byte, 1, 0, f))
return false;
cl->write_op_pos--;
if (!_flush_ssl())
return false;
cl->ssl_handshake_pending &= ~MSGR_HSP_SEND;
if (!msgr->finalize_tls_handshake(cl))
return false;
}
else if (!_flush_ssl())
return false;
if (!msgr->ssl_do_handshake(cl))
return;
}
return true;
_flush_ssl();
}
bool _flush_ssl()
@@ -154,8 +133,6 @@ public:
cl->ssl_more_to_buffer = true;
return false;
}
else
cl->ssl_more_to_buffer = false;
}
return true;
}
@@ -199,7 +176,7 @@ public:
from -= src_len;
return true;
}
if (!(flags & WR_GCM) || !cl->ssl_cli)
if (!(flags & WR_TLS) || !cl->ssl_cli)
{
if (flags & WR_XTS)
{
@@ -220,12 +197,12 @@ public:
}
else
{
if (cl->ssl_handshake_pending)
if (!cl->ssl_handshake_done)
{
if (!_flush_ssl())
if (!msgr->ssl_do_handshake(cl))
return false;
}
if (!cl->ssl_handshake_pending)
if (cl->ssl_handshake_done)
{
if (!write_to_ssl(cl, src, src_len, flags, from))
return false;
@@ -259,81 +236,17 @@ class gcm_op_writer_t: public msgr_op_writer_t
uint8_t *curbuf;
size_t bufsize;
size_t done;
uint32_t *batch_size_ptr;
public:
constexpr static bool is_ssl = false;
gcm_op_writer_t(osd_messenger_t* msgr, osd_client_t* cl, uint8_t *curbuf, size_t bufsize):
msgr(msgr), cl(cl), from(cl->write_op_pos), curbuf(curbuf), bufsize(bufsize), done(0)
msgr(msgr), cl(cl), from(cl->write_op_pos), curbuf(curbuf), bufsize(bufsize), done(0), batch_size_ptr(NULL)
{
}
void reset()
{
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
}
}
#ifdef WITH_ISAL_CRYPTO
int r = isal_aes_gcm_init_256(&cl->my_key_isal, cl->enc_ctx, cl->my_key.data() + AES_256_GCM_KEY_SIZE, 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*)cl->my_key.data(), cl->my_key.data() + AES_256_GCM_KEY_SIZE);
if (r != 1)
{
fprintf(stderr, "EncryptInit error: ");
ERR_print_errors_fp(stderr);
abort();
}
#endif
// Increase IV
cl->my_iv_ctr++;
(*(uint64_t*)(cl->my_key.data() + AES_256_GCM_KEY_SIZE))++;
}
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
@@ -343,7 +256,7 @@ public:
from -= src_len;
return true;
}
if (!(flags & WR_GCM))
if (!(flags & WR_TLS))
{
if (flags & WR_XTS)
{
@@ -366,15 +279,37 @@ public:
}
else
{
if (!cl->write_op_pos)
{
if (batch_size_ptr)
{
if (bufsize-done < 1)
return false;
(*batch_size_ptr)++;
}
else
{
if (bufsize-done < 5)
return false;
batch_size_ptr = (uint32_t*)(curbuf+done);
*batch_size_ptr = 1; // FIXME like header, but now for tests
done += 4;
cl->enc_batch = true;
uint8_t iv[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
int r = EVP_EncryptInit_ex(cl->enc_ctx, NULL, NULL, (uint8_t*)msgr->test_osd_aes_key.data(), iv);
if (r != 1)
{
fprintf(stderr, "EncryptInit error: ");
ERR_print_errors_fp(stderr);
abort();
}
}
}
size_t n = src_len-from;
if (n > bufsize-done)
n = bufsize-done;
if (!n)
return false;
#ifdef WITH_ISAL_CRYPTO
int r = isal_aes_gcm_enc_256_update(&cl->my_key_isal, cl->enc_ctx, curbuf+done, src+from, n);
assert(!r);
#else
int actual_out;
if (EVP_EncryptUpdate(cl->enc_ctx, curbuf+done, &actual_out, src+from, n) != 1)
{
@@ -383,7 +318,6 @@ public:
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);
done += n;
@@ -396,12 +330,8 @@ public:
return true;
}
static void write_tag_to(osd_messenger_t *msgr, osd_client_t *cl, uint8_t *dst)
static void write_tag_to(osd_client_t *cl, uint8_t *dst)
{
#ifdef WITH_ISAL_CRYPTO
int r = isal_aes_gcm_enc_256_finalize(&cl->my_key_isal, cl->enc_ctx, dst, 16);
assert(!r);
#else
int actual_out = 0;
int r = EVP_EncryptFinal_ex(cl->enc_ctx, NULL, &actual_out);
if (r != 1)
@@ -413,38 +343,26 @@ public:
assert(actual_out == 0);
r = EVP_CIPHER_CTX_ctrl(cl->enc_ctx, EVP_CTRL_GCM_GET_TAG, 16, dst);
assert(r == 1);
#endif
}
bool finish() override
{
if (bufsize-done >= OSD_PACKET_SIZE+16 && batch_size_ptr && cl->write_ops.size())
{
// More operations may fit, so don't finish the batch yet
return true;
}
// Tag is 16 bytes
if (done >= bufsize)
if (bufsize-done < 16)
{
// No space for the tag
return false;
if (bufsize-done < 16 || cl->enc_tag_size)
{
// No space for the full tag, but msgr_rdma expects us to always fill the whole buffer
if (!cl->enc_tag_size)
{
write_tag_to(msgr, cl, cl->enc_tag);
cl->enc_tag_size = 16;
}
size_t n = bufsize-done;
if (n > cl->enc_tag_size)
n = cl->enc_tag_size;
memcpy(curbuf+done, cl->enc_tag+16-cl->enc_tag_size, n);
done += n;
cl->enc_tag_size -= n;
if (cl->enc_tag_size > 0)
return false;
}
else
{
// The whole tag fits at once
write_tag_to(msgr, cl, curbuf+done);
done += 16;
}
free_ctx(msgr, cl);
write_tag_to(cl, curbuf+done);
done += 16;
// Batch is completed
cl->enc_batch = false;
batch_size_ptr = NULL;
return true;
}
@@ -454,15 +372,19 @@ public:
}
};
// FIXME Split into 3 classes - basic, tls and gcm
class get_op_writer_t: public msgr_op_writer_t
{
osd_messenger_t* msgr;
osd_client_t* cl;
size_t from;
size_t done;
size_t enc_size;
size_t done_enc;
bool have_batch;
size_t batch_size_offset;
size_t batch_bytes;
void ssl_extend_buf(size_t more = 0)
{
size_t min_cap = cl->ssl_out_buf_size*2;
@@ -472,18 +394,62 @@ class get_op_writer_t: public msgr_op_writer_t
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;
uint8_t *old_buf = cl->ssl_out_buf;
uint8_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);
if (iov.iov_base >= old_buf && iov.iov_base < old_end)
iov.iov_base = cl->ssl_out_buf + ((uint8_t*)iov.iov_base - old_buf);
}
}
}
void copy_ssl()
{
size_t prev_size = cl->ssl_out_buf_size;
do
{
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);
if (r > 0)
cl->ssl_out_buf_size += r;
} while (cl->ssl_out_buf_size >= cl->ssl_out_buf_cap);
if (cl->ssl_out_buf_size > prev_size)
{
cl->send_list.push_back((iovec){ .iov_base = cl->ssl_out_buf+prev_size, .iov_len = cl->ssl_out_buf_size-prev_size });
}
}
public:
get_op_writer_t(osd_messenger_t* msgr, osd_client_t* cl):
msgr(msgr), cl(cl), from(cl->write_op_pos), enc_size(0), done_enc(0),
have_batch(false), batch_size_offset(0), batch_bytes(0)
{
}
void reset()
{
from = cl->write_op_pos;
enc_size = 0;
done_enc = 0;
}
void flush_ssl()
{
if (!cl->ssl_handshake_done)
{
if (!msgr->ssl_do_handshake(cl))
return;
}
if (cl->send_list.size() >= IOV_MAX)
{
return;
}
copy_ssl();
}
void send_out_buf(size_t n)
{
if (cl->send_list.size() > 0)
@@ -497,72 +463,9 @@ class get_op_writer_t: public msgr_op_writer_t
}
}
cl->send_list.push_back((iovec){ .iov_base = cl->ssl_out_buf+cl->ssl_out_buf_size, .iov_len = n });
done += n;
cl->ssl_out_buf_size += n;
}
void copy_ssl()
{
size_t n = 0;
do
{
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);
if (r > 0)
n += r;
} while (cl->ssl_out_buf_size+n >= cl->ssl_out_buf_cap);
cl->ssl_more_to_buffer = false;
if (n > 0)
send_out_buf(n);
}
public:
constexpr static bool is_ssl = true;
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)
{
}
void reset()
{
from = cl->write_op_pos;
enc_size = 0;
done_enc = 0;
if (cl->gcm_enabled)
{
gcm_op_writer_t::init_ctx(msgr, cl);
}
}
bool flush_ssl()
{
if (cl->ssl_cli && cl->ssl_handshake_pending)
{
if (!msgr->do_tls_handshake(cl))
return false;
if (cl->ssl_handshake_pending & MSGR_HSP_SEND)
{
uint8_t first_byte = 0;
size_t f = 0;
if (!ssl_op_writer_t::write_to_ssl(cl, &first_byte, 1, 0, f))
return false;
cl->write_op_pos--;
copy_ssl();
cl->ssl_handshake_pending &= ~MSGR_HSP_SEND;
if (!msgr->finalize_tls_handshake(cl))
{
if (cl->gcm_enabled)
return true;
return false;
}
}
else
copy_ssl();
}
return true;
}
bool write(uint8_t *src, size_t src_len, int flags) override
{
if (from >= src_len)
@@ -575,18 +478,16 @@ public:
{
return false;
}
if (flags & WR_GCM)
if (flags & WR_TLS)
{
if (cl->ssl_cli)
{
if (cl->ssl_handshake_pending)
if (!cl->ssl_handshake_done)
{
if (!flush_ssl())
if (!msgr->ssl_do_handshake(cl))
return false;
if (cl->gcm_enabled)
goto try_gcm;
}
if (!cl->ssl_handshake_pending)
if (cl->ssl_handshake_done)
{
if (!ssl_op_writer_t::write_to_ssl(cl, src, src_len, flags, from))
return false;
@@ -598,16 +499,35 @@ public:
from = 0;
return true;
}
try_gcm:
if (cl->gcm_enabled)
else if (cl->enc_ctx)
{
// Encrypt data to client's temporary output buffer (all at once)
if (!cl->write_op_pos)
{
if (have_batch)
{
(*(uint32_t*)(cl->ssl_out_buf+batch_size_offset))++;
}
else
{
ssl_extend_buf(4);
have_batch = true;
batch_size_offset = cl->ssl_out_buf_size;
(*(uint32_t*)(cl->ssl_out_buf+batch_size_offset)) = 1;
send_out_buf(4);
cl->enc_batch = true;
uint8_t iv[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
int r = EVP_EncryptInit_ex(cl->enc_ctx, NULL, NULL, (uint8_t*)msgr->test_osd_aes_key.data(), iv);
if (r != 1)
{
fprintf(stderr, "EncryptInit error: ");
ERR_print_errors_fp(stderr);
abort();
}
}
}
size_t n = src_len-from;
ssl_extend_buf(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)
{
@@ -616,10 +536,10 @@ try_gcm:
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(n);
batch_bytes += n;
cl->write_op_pos += n;
from += n;
if (from < src_len)
@@ -643,19 +563,20 @@ try_gcm:
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;
}
assert(enc_size > 0);
size_t old_from = from;
msgr->op_encrypted_copy_buf(cl, cl->write_op->enc_buf, enc_size, src, src_len, from, done_enc);
assert(from == src_len);
batch_bytes += src_len-old_from;
}
else
{
if (cl->write_csum_state && !(flags & WR_NO_CSUM))
XXH3_64bits_update(cl->write_csum_state, src+from, src_len-from);
cl->send_list.push_back((iovec){ src+from, src_len-from });
done += src_len-from;
cl->write_op_pos += src_len-from;
batch_bytes += src_len-from;
}
from = 0;
return true;
@@ -673,19 +594,21 @@ try_gcm:
{
if (cl->send_list.size() >= IOV_MAX)
return false;
if (batch_bytes < 131072 && have_batch && cl->write_ops.size())
{
// More operations may fit, so don't finish the batch yet
return true;
}
// Tag is 16 bytes
ssl_extend_buf(16);
gcm_op_writer_t::write_tag_to(msgr, cl, cl->ssl_out_buf+cl->ssl_out_buf_size);
gcm_op_writer_t::write_tag_to(cl, cl->ssl_out_buf+cl->ssl_out_buf_size);
send_out_buf(16);
gcm_op_writer_t::free_ctx(msgr, cl);
cl->enc_batch = false;
have_batch = false;
batch_bytes = 0;
}
return true;
}
size_t get_done()
{
return done;
}
};
void osd_messenger_t::outbox_push(osd_op_t *cur_op)
@@ -797,6 +720,30 @@ void osd_messenger_t::measure_exec(osd_op_t *cur_op)
}
}
bool osd_messenger_t::ssl_do_handshake(osd_client_t *cl)
{
if (cl->ssl_handshake_done)
{
return true;
}
int r = SSL_do_handshake(cl->ssl_cli);
if (r > 0)
{
cl->ssl_handshake_done = true;
}
else
{
r = SSL_get_error(cl->ssl_cli, r);
if (r != 0 && r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE)
{
fprintf(stderr, "Client %ju TLS handshake error: %s, stopping client\n", cl->client_id, ERR_error_string(ERR_get_error(), NULL));
cl->io_error = true;
return false;
}
}
return true;
}
bool osd_messenger_t::try_send(osd_client_t *cl)
{
if (cl->peer_state == PEER_STOPPED || cl->peer_fd < 0)
@@ -808,11 +755,32 @@ bool osd_messenger_t::try_send(osd_client_t *cl)
return false;
}
assert(cl->peer_state != PEER_RDMA);
copy_ops_to_with<get_op_writer_t>(cl, NULL, 0);
if (cl->io_error)
get_op_writer_t wr(this, cl);
while ((cl->write_op || cl->write_ops.size()) && cl->send_list.size() < IOV_MAX)
{
stop_client(cl->client_id);
return true;
if (!cl->write_op)
{
next_write_op(cl);
wr.reset();
}
osd_op_t *op = cl->write_op;
if (!op_write_to(cl, wr))
{
if (cl->io_error)
{
stop_client(cl->client_id);
return true;
}
break;
}
if (!cl->write_op && op->op_type == OSD_OP_IN)
{
cl->send_free_ops.push_back(op);
}
}
if (!cl->send_list.size() && cl->ssl_cli)
{
wr.flush_ssl();
}
if (!cl->send_list.size())
{
@@ -878,13 +846,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)
{
if (cl->ssl_cli)
{
size_t done = copy_ops_to_with<ssl_op_writer_t>(cl, dst, dst_len);
if (done > 0 || cl->ssl_cli || !cl->gcm_enabled)
return done;
}
if (cl->gcm_enabled)
if (cl->enc_ctx)
{
return copy_ops_to_with<gcm_op_writer_t>(cl, dst, dst_len);
}
@@ -915,13 +877,10 @@ size_t osd_messenger_t::copy_ops_to_with(osd_client_t *cl, uint8_t *dst, size_t
cl->send_free_ops.push_back(op);
}
}
if constexpr (T::is_ssl)
/*FIXME if (!wr.get_done() && cl->ssl_cli)
{
if (!wr.get_done())
{
wr.flush_ssl();
}
}
wr.flush_ssl();
}*/
return wr.get_done();
}
@@ -933,10 +892,7 @@ void osd_messenger_t::next_write_op(osd_client_t *cl)
{
if (!cl->write_csum_state)
cl->write_csum_state = XXH3_createState();
if (cl->my_key.size() == AES_256_GCM_KEY_SIZE + AES_256_GCM_IV_SIZE + XXH_SECRET_DEFAULT_SIZE)
XXH3_64bits_reset_withSecret(cl->write_csum_state, cl->my_key.data() + AES_256_GCM_KEY_SIZE + AES_256_GCM_IV_SIZE, XXH_SECRET_DEFAULT_SIZE);
else
XXH3_64bits_reset(cl->write_csum_state);
XXH3_64bits_reset(cl->write_csum_state);
}
}
@@ -1081,7 +1037,7 @@ bool osd_messenger_t::op_write_to(osd_client_t *cl, msgr_op_writer_t & wr)
osd_op_t *op = cl->write_op;
// Header
if (!wr.write((op->op_type == OSD_OP_IN ? op->reply.buf : op->req.buf), OSD_PACKET_SIZE,
WR_GCM | (cl->proto_csum_status == MSGR_CSUM_PAYLOAD ? WR_NO_CSUM : 0)))
WR_TLS | (cl->proto_csum_status == MSGR_CSUM_PAYLOAD ? WR_NO_CSUM : 0)))
{
return false;
}
@@ -1090,17 +1046,17 @@ bool osd_messenger_t::op_write_to(osd_client_t *cl, msgr_op_writer_t & wr)
{
if (op->req.hdr.opcode == OSD_OP_SEC_READ && op->reply.sec_rw.attr_len > 0)
{
if (!wr.write((uint8_t*)op->bitmap, op->reply.sec_rw.attr_len, WR_GCM))
if (!wr.write((uint8_t*)op->bitmap, op->reply.sec_rw.attr_len, WR_TLS))
return false;
}
else if (op->req.hdr.opcode == OSD_OP_SEC_READ_BMP && op->reply.hdr.retval > 0)
{
if (!wr.write((uint8_t*)op->buf, (size_t)op->reply.hdr.retval, WR_GCM))
if (!wr.write((uint8_t*)op->buf, (size_t)op->reply.hdr.retval, WR_TLS))
return false;
}
else if (op->req.hdr.opcode == OSD_OP_READ && op->reply.rw.bitmap_len > 0)
{
if (!wr.write((uint8_t*)op->bitmap, op->reply.rw.bitmap_len, WR_GCM))
if (!wr.write((uint8_t*)op->bitmap, op->reply.rw.bitmap_len, WR_TLS))
return false;
}
}
@@ -1109,12 +1065,12 @@ bool osd_messenger_t::op_write_to(osd_client_t *cl, msgr_op_writer_t & wr)
if ((op->req.hdr.opcode == OSD_OP_SEC_WRITE || op->req.hdr.opcode == OSD_OP_SEC_WRITE_STABLE) &&
op->req.sec_rw.attr_len > 0)
{
if (!wr.write((uint8_t*)op->bitmap, op->req.sec_rw.attr_len, WR_GCM))
if (!wr.write((uint8_t*)op->bitmap, op->req.sec_rw.attr_len, WR_TLS))
return false;
}
else if (op->req.hdr.opcode == OSD_OP_SEC_READ_BMP && op->req.sec_read_bmp.len > 0)
{
if (!wr.write((uint8_t*)op->buf, (size_t)op->req.sec_read_bmp.len, WR_GCM))
if (!wr.write((uint8_t*)op->buf, (size_t)op->req.sec_read_bmp.len, WR_TLS))
return false;
}
}
@@ -1124,7 +1080,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, WR_GCM))
if (!wr.write((uint8_t*)iov.iov_base, iov.iov_len, WR_TLS))
return false;
}
}
@@ -1141,7 +1097,7 @@ bool osd_messenger_t::op_write_to(osd_client_t *cl, msgr_op_writer_t & wr)
cl->proto_csum_status == MSGR_CSUM_PAYLOAD && cl->write_op_pos > OSD_PACKET_SIZE)
{
cl->write_op->csum = XXH3_64bits_digest(cl->write_csum_state);
if (!wr.write((uint8_t*)&cl->write_op->csum, 8, WR_GCM|WR_NO_CSUM))
if (!wr.write((uint8_t*)&cl->write_op->csum, 8, WR_TLS|WR_NO_CSUM))
return false;
}
if (!wr.finish())
+20 -18
View File
@@ -9,10 +9,12 @@
#ifdef WITH_RDMA
#include "msgr_rdma.h"
#endif
#ifdef WITH_OPENSSL
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#endif
void osd_client_t::cancel_ops()
{
@@ -84,21 +86,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);
}
}
if (cl->xts_enc_ctx)
if (cl->encrypt_ctx)
{
if (encrypt_xts_pool.size() > max_cipher_pool_size)
destroy_aes_xts_encrypt(cl->xts_enc_ctx);
if (encrypt_ctx_pool.size() > max_aes_xts_pool_size)
destroy_aes_xts_encrypt(cl->encrypt_ctx);
else
encrypt_xts_pool.push_back(cl->xts_enc_ctx);
cl->xts_enc_ctx = NULL;
encrypt_ctx_pool.push_back(cl->encrypt_ctx);
cl->encrypt_ctx = NULL;
}
if (cl->xts_dec_ctx)
if (cl->decrypt_ctx)
{
if (decrypt_xts_pool.size() > max_cipher_pool_size)
destroy_aes_xts_decrypt(cl->xts_dec_ctx);
if (decrypt_ctx_pool.size() > max_aes_xts_pool_size)
destroy_aes_xts_decrypt(cl->decrypt_ctx);
else
decrypt_xts_pool.push_back(cl->xts_dec_ctx);
cl->xts_dec_ctx = NULL;
decrypt_ctx_pool.push_back(cl->decrypt_ctx);
cl->decrypt_ctx = NULL;
}
// First set state to STOPPED so another stop_client() call doesn't try to free it again
cl->refs++;
@@ -208,6 +210,12 @@ osd_client_t::~osd_client_t()
read_op->cancel();
read_op = NULL;
}
while (unverified_ops.size())
{
auto op = unverified_ops.back();
unverified_ops.pop_back();
op->cancel();
}
// Cancel outbound ops
cancel_ops();
for (osd_op_t *op: send_free_ops)
@@ -246,22 +254,15 @@ osd_client_t::~osd_client_t()
XXH3_freeState(write_csum_state);
write_csum_state = NULL;
}
#ifdef WITH_OPENSSL
if (enc_ctx)
{
#ifdef WITH_ISAL_CRYPTO
free(enc_ctx);
#else
EVP_CIPHER_CTX_free(enc_ctx);
#endif
enc_ctx = NULL;
}
if (dec_ctx)
{
#ifdef WITH_ISAL_CRYPTO
free(dec_ctx);
#else
EVP_CIPHER_CTX_free(dec_ctx);
#endif
dec_ctx = NULL;
}
if (ssl_cli)
@@ -276,4 +277,5 @@ osd_client_t::~osd_client_t()
free(ssl_out_buf);
ssl_out_buf = NULL;
}
#endif
}
+4
View File
@@ -1,7 +1,9 @@
// Copyright (c) Vitaliy Filippov, 2019+
// License: VNPL-1.1 (see README.md for details)
#ifdef WITH_OPENSSL
#include <openssl/rand.h>
#endif
#include <ctype.h>
#include "cli.h"
@@ -626,12 +628,14 @@ std::function<bool(cli_result_t &)> cli_tool_t::start_create(json11::Json cfg)
if (!cfg["enc_key"].is_null())
{
image_creator->set_key = true;
#ifdef WITH_OPENSSL
if (image_creator->enc_key == "random")
{
uint8_t newkey[64];
RAND_bytes(newkey, 64);
image_creator->enc_key = tohexstr(newkey, 64);
}
#endif
else
{
image_creator->enc_key = cfg["enc_key"].string_value();
+1 -2
View File
@@ -121,7 +121,6 @@ static const char* help_text =
" --logfile <FILE> log to the specified file\n"
" --enforce 1 enforce permissions at the server side (default is disabled)\n"
" --foreground 1 stay in foreground, do not daemonize\n"
" --trace trace all NFS requests\n"
"\n"
"NFS proxy is stateless if you use immediate_commit=all in your cluster and if\n"
"you do not use client_enable_writeback=true, so you can freely use multiple\n"
@@ -159,7 +158,7 @@ json11::Json::object nfs_proxy_t::parse_args(int narg, const char *args[])
{
const char *opt = args[i]+2;
cfg[str_replace(opt, "-", "_")] = !strcmp(opt, "json") || !strcmp(opt, "block") ||
!strcmp(opt, "dry-run") || !strcmp(opt, "recalc-stats") || !strcmp(opt, "trace") ||
!strcmp(opt, "dry-run") || !strcmp(opt, "recalc-stats") ||
!strcmp(opt, "include-empty") || !strcmp(opt, "no-rm") || i == narg-1 ? "1" : args[++i];
}
else
-2
View File
@@ -83,8 +83,6 @@ void osd_t::finish_op(osd_op_t *cur_op, int retval)
rm_inflight(pg);
}
assert(!cur_op->op_data->subops);
free(cur_op->op_data);
cur_op->op_data = NULL;
}
cur_op->reply.hdr.magic = SECONDARY_OSD_REPLY_MAGIC;
cur_op->reply.hdr.id = cur_op->req.hdr.id;
+11 -5
View File
@@ -1,7 +1,9 @@
// Copyright (c) Vitaliy Filippov, 2019+
// License: VNPL-1.1 (see README.md for details)
#ifdef WITH_OPENSSL
#include <openssl/rand.h>
#endif
#include <stdio.h>
#include <stdlib.h>
@@ -554,6 +556,7 @@ void test_writeback_merge()
printf("[ok] writeback merge test\n");
}
#ifdef WITH_OPENSSL
void test_msgr_encrypt()
{
const size_t sz = 1048576;
@@ -592,7 +595,7 @@ void test_msgr_encrypt()
enc->start(key, 4096 * 114, 4096);
in_pos = out_pos = 0;
enc->update(src+4096, 4096, crypt2, 4095, in_pos, out_pos);
assert(in_pos == 4095);
assert(in_pos == 4096);
assert(out_pos == 4095);
enc->update(src+4096+in_pos, 4096-in_pos, crypt2+out_pos, 4096-out_pos, in_pos, out_pos);
assert(in_pos == 4096);
@@ -623,10 +626,10 @@ void test_msgr_encrypt()
assert(in_pos == 3000);
assert(out_pos == 0);
dec->update(crypt+4096+3000, 3000, decrypt, 500, in_pos, out_pos);
assert(in_pos == 4095);
assert(in_pos == 4096);
assert(out_pos == 500);
dec->update(crypt+4096+in_pos, 6000-in_pos, decrypt+out_pos, 3000, in_pos, out_pos);
assert(in_pos == 4095);
assert(in_pos == 4096);
assert(out_pos == 3500);
dec->update(crypt+4096+in_pos, 6000-in_pos, decrypt+out_pos, 1000, in_pos, out_pos);
assert(in_pos == 4096);
@@ -635,10 +638,10 @@ void test_msgr_encrypt()
assert(in_pos == 6000);
assert(out_pos == 4096);
dec->update(crypt+4096+in_pos, 8192-in_pos, decrypt+out_pos, 4500-out_pos, in_pos, out_pos);
assert(in_pos == 8191);
assert(in_pos == 8192);
assert(out_pos == 4500);
dec->update(crypt+4096+in_pos, 8192-in_pos, decrypt+out_pos, 7500-out_pos, in_pos, out_pos);
assert(in_pos == 8191);
assert(in_pos == 8192);
assert(out_pos == 7500);
dec->update(crypt+4096+in_pos, 8192-in_pos, decrypt+out_pos, 8192-out_pos, in_pos, out_pos);
assert(in_pos == 8192);
@@ -722,6 +725,7 @@ void test_msgr_decrypt_chain()
free(src);
printf("[ok] msgr aes-xts chained decrypt\n");
}
#endif
void test_vault()
{
@@ -790,8 +794,10 @@ int main(int narg, char *args[])
test2();
test_writeback();
test_writeback_merge();
#ifdef WITH_OPENSSL
test_msgr_encrypt();
test_msgr_decrypt_chain();
#endif
test_vault();
return 0;
}
-119
View File
@@ -1,119 +0,0 @@
// Copyright (c) Vitaliy Filippov, 2019+
// License: VNPL-1.1 or GNU GPL-2.0+ (see README.md for details)
#include "openssl_util.h"
#include "str_util.h"
#include <openssl/ssl.h>
X509 *openssl_load_cert(const std::string & file_or_pem)
{
std::string pem;
BIO *bio = NULL;
if (file_or_pem.substr(0, 5) != "-----")
{
pem = read_file(file_or_pem);
bio = BIO_new_mem_buf(pem.data(), pem.size());
}
else
bio = BIO_new_mem_buf(file_or_pem.data(), file_or_pem.size());
if (!bio)
return NULL;
X509 *x509 = PEM_read_bio_X509(bio, NULL, 0, NULL);
BIO_free(bio);
return x509;
}
bool openssl_ctx_add_ca(SSL_CTX *ssl_ctx, const std::string & file_or_pem)
{
X509 *cert = openssl_load_cert(file_or_pem);
bool ok = !!cert;
if (cert)
{
X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx);
X509_STORE_add_cert(store, cert);
X509_free(cert);
}
return ok;
}
bool openssl_ctx_use_ca(SSL_CTX *ssl_ctx, const std::string & file_or_pem)
{
if (file_or_pem.substr(0, 5) == "-----")
{
return openssl_ctx_add_ca(ssl_ctx, file_or_pem);
}
return file_or_pem.empty()
? !!SSL_CTX_set_default_verify_paths(ssl_ctx)
: !!SSL_CTX_load_verify_locations(ssl_ctx, file_or_pem.c_str(), NULL);
}
std::string openssl_get_cn(X509 *x509)
{
X509_NAME* subj = X509_get_subject_name(x509);
int pos = X509_NAME_get_index_by_NID(subj, NID_commonName, -1);
if (pos != -1)
{
X509_NAME_ENTRY* cn = X509_NAME_get_entry(subj, pos);
ASN1_STRING* str = X509_NAME_ENTRY_get_data(cn);
return std::string((const char*)ASN1_STRING_get0_data(str), ASN1_STRING_length(str));
}
return "";
}
bool openssl_ctx_use_cert(SSL_CTX *ssl_ctx, const std::string & file_or_pem, std::string & common_name)
{
BIO *bio = NULL;
std::string contents;
if (file_or_pem.substr(0, 5) == "-----")
bio = BIO_new_mem_buf(file_or_pem.data(), file_or_pem.size());
else
{
contents = read_file(file_or_pem);
if (!contents.size())
return false;
bio = BIO_new_mem_buf(contents.data(), contents.size());
}
if (!bio)
return false;
X509 *x509 = PEM_read_bio_X509(bio, NULL, 0, NULL);
bool ok = !!x509;
if (x509)
{
ok = SSL_CTX_use_certificate(ssl_ctx, x509);
if (ok)
common_name = openssl_get_cn(x509);
X509_free(x509);
}
BIO_free(bio);
return ok;
}
bool openssl_ctx_use_key(SSL_CTX *ssl_ctx, const std::string & file_or_pem)
{
if (file_or_pem.substr(0, 5) == "-----")
{
BIO *bio = BIO_new_mem_buf(file_or_pem.data(), file_or_pem.size());
if (!bio)
return false;
EVP_PKEY *pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
bool ok = !!pkey;
if (pkey)
{
ok = SSL_CTX_use_PrivateKey(ssl_ctx, pkey);
EVP_PKEY_free(pkey);
}
BIO_free(bio);
return ok;
}
return !!SSL_CTX_use_PrivateKey_file(ssl_ctx, file_or_pem.c_str(), SSL_FILETYPE_PEM);
}
bool openssl_bio_nonempty(BIO *bio)
{
// SSL_ERROR_WANT_WRITE is absolutely non-informative with memory BIO, it basically never happens
// So we have to check memory BIO for outstanding data
char *bio_buf = NULL;
size_t bio_sz = BIO_get_mem_data(bio, &bio_buf);
return bio_sz > 0;
}
-18
View File
@@ -1,18 +0,0 @@
// Copyright (c) Vitaliy Filippov, 2019+
// License: VNPL-1.1 or GNU GPL-2.0+ (see README.md for details)
#pragma once
#include <string>
#ifdef WITH_OPENSSL
#include <openssl/types.h>
#endif
X509 *openssl_load_cert(const std::string & file_or_pem);
bool openssl_ctx_add_ca(SSL_CTX *ssl_ctx, const std::string & file_or_pem);
bool openssl_ctx_use_ca(SSL_CTX *ssl_ctx, const std::string & file_or_pem);
std::string openssl_get_cn(X509 *x509);
bool openssl_ctx_use_cert(SSL_CTX *ssl_ctx, const std::string & file_or_pem, std::string & common_name);
bool openssl_ctx_use_key(SSL_CTX *ssl_ctx, const std::string & file_or_pem);
bool openssl_bio_nonempty(BIO *bio);
+4 -9
View File
@@ -535,12 +535,12 @@ std::string urldecode(const std::string & orig)
return res;
}
size_t fromhexstr(const char *from, size_t from_len, uint8_t *to, size_t to_len)
size_t fromhexstr(const std::string & from, size_t bytes, uint8_t *to)
{
if (to_len > from_len/2)
to_len = from_len/2;
if (bytes > from.size()/2)
bytes = from.size()/2;
size_t i = 0;
while (i < to_len)
while (i < bytes)
{
uint8_t x = fromhexchar(from[2*i], 16);
uint8_t y = fromhexchar(from[2*i+1], 16);
@@ -552,11 +552,6 @@ size_t fromhexstr(const char *from, size_t from_len, uint8_t *to, size_t to_len)
return i;
}
size_t fromhexstr(const std::string & from, size_t bytes, uint8_t *to)
{
return fromhexstr(from.data(), from.size(), to, bytes);
}
std::string tohexstr(const uint8_t *from, size_t bytes)
{
std::string res;
-1
View File
@@ -35,7 +35,6 @@ std::string realpath_str(std::string path, bool nofail = true);
std::string format_datetime(uint64_t unixtime);
bool is_zero(void *buf, size_t size);
std::string urldecode(const std::string & orig);
size_t fromhexstr(const char *from, size_t from_len, uint8_t *to, size_t to_len);
size_t fromhexstr(const std::string & from, size_t bytes, uint8_t *to);
std::string tohexstr(const uint8_t *from, size_t bytes);
bool ishexstr(const std::string & str);
-2
View File
@@ -34,8 +34,6 @@ extern "C" {
# define XXH_NOESCAPE
#endif
#define XXH_SECRET_DEFAULT_SIZE 192
typedef enum {
XXH_OK = 0,
XXH_ERROR
+2 -1
View File
@@ -27,7 +27,7 @@ ETCD_COUNT=${ETCD_COUNT:-1}
ANTIETCD=${ANTIETCD}
USE_RAMDISK=${USE_RAMDISK}
ETCD_SCHEME=${ETCD_SCHEME:-http}
OSD_TLS=${OSD_TLS:-1}
OSD_TLS=${OSD_TLS}
RAMDISK=/run/user/$(id -u)
findmnt $RAMDISK >/dev/null || (sudo mkdir -p $RAMDISK && sudo mount -t tmpfs tmpfs $RAMDISK)
@@ -142,6 +142,7 @@ if [[ "$OSD_TLS" = "1" ]]; then
VITASTOR_CFG="$VITASTOR_CFG"',"tls_cert":"'$(pwd)'/testdata/cli.crt"'
VITASTOR_CFG="$VITASTOR_CFG"',"tls_key":"'$(pwd)'/testdata/cli.key"'
fi
VITASTOR_CFG="$VITASTOR_CFG"',"test_osd_aes_key":"'$(openssl rand -hex 32)'"'
echo "{$VITASTOR_CFG}" > ./testdata/vitastor.conf
VITASTOR_CFG=./testdata/vitastor.conf
VITASTOR_CLI="build/src/cmd/vitastor-cli --config_path $VITASTOR_CFG"