From 469b432ebeb489ba13a1fa30ca713723800fa83f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Tue, 27 Jun 2017 00:29:12 +0300 Subject: [PATCH 1/3] Detect and handle OpenSSL 1.1 OpenSSL 1.1 supports most of the native threading libraries, including pthread. This means that only versions before 1.1 need the thread handling code. --- CMakeLists.txt | 4 +++- server/core/gateway.cc | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 96d02b648..c98aa7f62 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,8 +84,10 @@ if(NOT OPENSSL_FOUND) else() if(OPENSSL_VERSION VERSION_LESS 1 AND NOT FORCE_OPENSSL100) add_definitions("-DOPENSSL_0_9") - else() + elseif(OPENSSL_VERSION VERSION_LESS 1.1) add_definitions("-DOPENSSL_1_0") + else() + add_definitions("-DOPENSSL_1_1") endif() endif() diff --git a/server/core/gateway.cc b/server/core/gateway.cc index b34196590..7adf4a317 100644 --- a/server/core/gateway.cc +++ b/server/core/gateway.cc @@ -189,6 +189,7 @@ static void modules_process_finish(); static bool modules_thread_init(); static void modules_thread_finish(); +#ifndef OPENSSL_1_1 /** SSL multi-threading functions and structures */ static SPINLOCK* ssl_locks; @@ -270,6 +271,7 @@ static void maxscale_ssl_id(CRYPTO_THREADID* id) CRYPTO_THREADID_set_numeric(id, pthread_self()); } #endif +#endif /** * Handler for SIGHUP signal. Reload the configuration for the @@ -1741,6 +1743,7 @@ int main(int argc, char **argv) SSL_load_error_strings(); OPENSSL_add_all_algorithms_noconf(); +#ifndef OPENSSL_1_1 numlocks = CRYPTO_num_locks(); if ((ssl_locks = (SPINLOCK*)MXS_MALLOC(sizeof(SPINLOCK) * (numlocks + 1))) == NULL) { @@ -1760,6 +1763,7 @@ int main(int argc, char **argv) CRYPTO_THREADID_set_callback(maxscale_ssl_id); #else CRYPTO_set_id_callback(pthread_self); +#endif #endif /** From a47d4c40f5d1e4bc8634acc12489b1631f3deb65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Tue, 27 Jun 2017 00:54:19 +0300 Subject: [PATCH 2/3] Abstract EVP cipher context creation The EVP_CIPHER_CTX is now created inside a wrapper function to add support for OpenSSL 1.1. Also fixed improper use of the EVP_CIPHER_CTX internals in binlogrouter. --- include/maxscale/encryption.h | 25 +++++++++++ server/core/CMakeLists.txt | 2 +- server/core/encryption.c | 37 +++++++++++++++++ .../modules/routing/binlogrouter/blr_file.c | 41 +++++++++---------- 4 files changed, 83 insertions(+), 22 deletions(-) create mode 100644 include/maxscale/encryption.h create mode 100644 server/core/encryption.c diff --git a/include/maxscale/encryption.h b/include/maxscale/encryption.h new file mode 100644 index 000000000..dfbb3407a --- /dev/null +++ b/include/maxscale/encryption.h @@ -0,0 +1,25 @@ +#pragma once +/* + * Copyright (c) 2016 MariaDB Corporation Ab + * + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file and at www.mariadb.com/bsl11. + * + * Change Date: 2020-01-01 + * + * On the date above, in accordance with the Business Source License, use + * of this software will be governed by version 2 or later of the General + * Public License. + */ + +#include + +#include + +MXS_BEGIN_DECLS + + +EVP_CIPHER_CTX* mxs_evp_cipher_ctx_alloc(); +void mxs_evp_cipher_ctx_free(EVP_CIPHER_CTX* ctx); + +MXS_END_DECLS diff --git a/server/core/CMakeLists.txt b/server/core/CMakeLists.txt index 79761cdc8..2f2bcadc2 100644 --- a/server/core/CMakeLists.txt +++ b/server/core/CMakeLists.txt @@ -1,4 +1,4 @@ -add_library(maxscale-common SHARED adminusers.c alloc.c authenticator.c atomic.c buffer.c config.c config_runtime.c dcb.c filter.c filter.cc externcmd.c paths.c hashtable.c hint.c housekeeper.c load_utils.c log_manager.cc maxscale_pcre2.c misc.c mlist.c modutil.c monitor.c queuemanager.c query_classifier.cc poll.c random_jkiss.c resultset.c secrets.c server.c service.c session.c spinlock.c thread.c users.c utils.c skygw_utils.cc statistics.c listener.c ssl.c mysql_utils.c mysql_binlog.c modulecmd.c) +add_library(maxscale-common SHARED adminusers.c alloc.c authenticator.c atomic.c buffer.c config.c config_runtime.c dcb.c filter.c filter.cc externcmd.c paths.c hashtable.c hint.c housekeeper.c load_utils.c log_manager.cc maxscale_pcre2.c misc.c mlist.c modutil.c monitor.c queuemanager.c query_classifier.cc poll.c random_jkiss.c resultset.c secrets.c server.c service.c session.c spinlock.c thread.c users.c utils.c skygw_utils.cc statistics.c listener.c ssl.c mysql_utils.c mysql_binlog.c modulecmd.c encryption.c) if(WITH_JEMALLOC) target_link_libraries(maxscale-common ${JEMALLOC_LIBRARIES}) diff --git a/server/core/encryption.c b/server/core/encryption.c new file mode 100644 index 000000000..219cd8916 --- /dev/null +++ b/server/core/encryption.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016 MariaDB Corporation Ab + * + * Use of this software is governed by the Business Source License included + * in the LICENSE.TXT file and at www.mariadb.com/bsl11. + * + * Change Date: 2020-01-01 + * + * On the date above, in accordance with the Business Source License, use + * of this software will be governed by version 2 or later of the General + * Public License. + */ + +#include + +#include +#include + +EVP_CIPHER_CTX* mxs_evp_cipher_ctx_alloc() +{ +#ifdef OPENSSL_1_1 + return EVP_CIPHER_CTX_new(); +#else + EVP_CIPHER_CTX* rval = (EVP_CIPHER_CTX*)MXS_MALLOC(sizeof(*rval)); + EVP_CIPHER_CTX_init(rval); + return rval; +#endif +} + +void mxs_evp_cipher_ctx_free(EVP_CIPHER_CTX* ctx) +{ +#ifdef OPENSSL_1_1 + EVP_CIPHER_CTX_free(ctx); +#else + MXS_FREE(ctx); +#endif +} diff --git a/server/modules/routing/binlogrouter/blr_file.c b/server/modules/routing/binlogrouter/blr_file.c index 34ea645f7..033d0c328 100644 --- a/server/modules/routing/binlogrouter/blr_file.c +++ b/server/modules/routing/binlogrouter/blr_file.c @@ -72,6 +72,7 @@ #include #include #include +#include /** * AES_CTR handling @@ -2796,7 +2797,6 @@ static GWBUF *blr_aes_crypt(ROUTER_INSTANCE *router, uint8_t *iv, int action) { - EVP_CIPHER_CTX ctx; uint8_t *key = router->encryption.key_value; unsigned int key_len = router->encryption.key_len; int outlen; @@ -2819,10 +2819,10 @@ static GWBUF *blr_aes_crypt(ROUTER_INSTANCE *router, out_ptr = GWBUF_DATA(outbuf); - EVP_CIPHER_CTX_init(&ctx); + EVP_CIPHER_CTX *ctx = mxs_evp_cipher_ctx_alloc(); /* Set the encryption algorithm accordingly to key_len and encryption mode */ - if (!EVP_CipherInit_ex(&ctx, + if (!EVP_CipherInit_ex(ctx, ciphers[router->encryption.encryption_algorithm](router->encryption.key_len), NULL, key, @@ -2830,23 +2830,23 @@ static GWBUF *blr_aes_crypt(ROUTER_INSTANCE *router, action)) { MXS_ERROR("Error in EVP_CipherInit_ex for algo %d", router->encryption.encryption_algorithm); - EVP_CIPHER_CTX_cleanup(&ctx); + mxs_evp_cipher_ctx_free(ctx); MXS_FREE(outbuf); return NULL; } /* Set no padding */ - EVP_CIPHER_CTX_set_padding(&ctx, 0); + EVP_CIPHER_CTX_set_padding(ctx, 0); /* Encryt/Decrypt the input data */ - if (!EVP_CipherUpdate(&ctx, + if (!EVP_CipherUpdate(ctx, out_ptr + 4, &outlen, buffer, size)) { MXS_ERROR("Error in EVP_CipherUpdate"); - EVP_CIPHER_CTX_cleanup(&ctx); + mxs_evp_cipher_ctx_free(ctx); MXS_FREE(outbuf); return NULL; } @@ -2857,7 +2857,7 @@ static GWBUF *blr_aes_crypt(ROUTER_INSTANCE *router, if (router->encryption.encryption_algorithm != BLR_AES_CBC) { /* Call Final_ex */ - if (!EVP_CipherFinal_ex(&ctx, + if (!EVP_CipherFinal_ex(ctx, (out_ptr + 4 + outlen), (int*)&flen)) { @@ -2871,12 +2871,12 @@ static GWBUF *blr_aes_crypt(ROUTER_INSTANCE *router, * If some bytes (ctx.buf_len) are still available in ctx.buf * handle them with ECB and XOR */ - if (ctx.buf_len) + if (size - outlen > 0) { if (!blr_aes_create_tail_for_cbc(out_ptr + 4 + outlen, - ctx.buf, - ctx.buf_len, - ctx.oiv, + buffer + outlen, + size - outlen, + iv, router->encryption.key_value, router->encryption.key_len)) { @@ -2892,7 +2892,7 @@ static GWBUF *blr_aes_crypt(ROUTER_INSTANCE *router, outbuf = NULL; } - EVP_CIPHER_CTX_cleanup(&ctx); + mxs_evp_cipher_ctx_free(ctx); return outbuf; } @@ -3070,14 +3070,13 @@ static int blr_aes_create_tail_for_cbc(uint8_t *output, uint8_t *key, unsigned int key_len) { - EVP_CIPHER_CTX t_ctx; uint8_t mask[AES_BLOCK_SIZE]; int mlen = 0; - EVP_CIPHER_CTX_init(&t_ctx); + EVP_CIPHER_CTX* t_ctx = mxs_evp_cipher_ctx_alloc(); /* Initialise with AES_ECB and NULL iv */ - if (!EVP_CipherInit_ex(&t_ctx, + if (!EVP_CipherInit_ex(t_ctx, ciphers[BLR_AES_ECB](key_len), NULL, key, @@ -3085,22 +3084,22 @@ static int blr_aes_create_tail_for_cbc(uint8_t *output, BINLOG_FLAG_ENCRYPT)) { MXS_ERROR("Error in EVP_CipherInit_ex CBC for last block (ECB)"); - EVP_CIPHER_CTX_cleanup(&t_ctx); + mxs_evp_cipher_ctx_free(t_ctx); return 0; } /* Set no padding */ - EVP_CIPHER_CTX_set_padding(&t_ctx, 0); + EVP_CIPHER_CTX_set_padding(t_ctx, 0); /* Do the enc/dec of the IV (the one from previous stage) */ - if (!EVP_CipherUpdate(&t_ctx, + if (!EVP_CipherUpdate(t_ctx, mask, &mlen, iv, sizeof(mask))) { MXS_ERROR("Error in EVP_CipherUpdate ECB"); - EVP_CIPHER_CTX_cleanup(&t_ctx); + mxs_evp_cipher_ctx_free(t_ctx); return 0; } @@ -3115,7 +3114,7 @@ static int blr_aes_create_tail_for_cbc(uint8_t *output, output[i] = input[i] ^ mask[i]; } - EVP_CIPHER_CTX_cleanup(&t_ctx); + mxs_evp_cipher_ctx_free(t_ctx); return 1; } From 322fae832614bc2e0786d41e09b13f8cbba5b686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Thu, 29 Jun 2017 13:46:06 +0300 Subject: [PATCH 3/3] Add wrapper functions for buffer and original IV access Added functions for accessing the buffer and original IV. This hides the changes introduced in OpenSSL 1.1. --- include/maxscale/encryption.h | 2 ++ server/core/encryption.c | 18 ++++++++++++++++++ server/modules/routing/binlogrouter/blr_file.c | 4 ++-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/include/maxscale/encryption.h b/include/maxscale/encryption.h index dfbb3407a..48b928856 100644 --- a/include/maxscale/encryption.h +++ b/include/maxscale/encryption.h @@ -21,5 +21,7 @@ MXS_BEGIN_DECLS EVP_CIPHER_CTX* mxs_evp_cipher_ctx_alloc(); void mxs_evp_cipher_ctx_free(EVP_CIPHER_CTX* ctx); +uint8_t* mxs_evp_cipher_ctx_buf(EVP_CIPHER_CTX* ctx); +uint8_t* mxs_evp_cipher_ctx_oiv(EVP_CIPHER_CTX* ctx); MXS_END_DECLS diff --git a/server/core/encryption.c b/server/core/encryption.c index 219cd8916..63f9b2c4b 100644 --- a/server/core/encryption.c +++ b/server/core/encryption.c @@ -35,3 +35,21 @@ void mxs_evp_cipher_ctx_free(EVP_CIPHER_CTX* ctx) MXS_FREE(ctx); #endif } + +uint8_t* mxs_evp_cipher_ctx_buf(EVP_CIPHER_CTX* ctx) +{ +#ifdef OPENSSL_1_1 + return (uint8_t*)EVP_CIPHER_CTX_buf_noconst(ctx); +#else + return (uint8_t*)ctx->buf; +#endif +} + +uint8_t* mxs_evp_cipher_ctx_oiv(EVP_CIPHER_CTX* ctx) +{ +#ifdef OPENSSL_1_1 + return (uint8_t*)EVP_CIPHER_CTX_original_iv(ctx); +#else + return (uint8_t*)ctx->oiv; +#endif +} diff --git a/server/modules/routing/binlogrouter/blr_file.c b/server/modules/routing/binlogrouter/blr_file.c index 033d0c328..96c2a18f4 100644 --- a/server/modules/routing/binlogrouter/blr_file.c +++ b/server/modules/routing/binlogrouter/blr_file.c @@ -2874,9 +2874,9 @@ static GWBUF *blr_aes_crypt(ROUTER_INSTANCE *router, if (size - outlen > 0) { if (!blr_aes_create_tail_for_cbc(out_ptr + 4 + outlen, - buffer + outlen, + mxs_evp_cipher_ctx_buf(ctx), size - outlen, - iv, + mxs_evp_cipher_ctx_oiv(ctx), router->encryption.key_value, router->encryption.key_len)) {