PKGBUILDs/extra/mariadb/0001-openssl-1-1-0.patch
2018-02-12 14:09:02 +00:00

1017 lines
34 KiB
Diff

diff --git a/extra/yassl/src/handshake.cpp b/extra/yassl/src/handshake.cpp
index 407e409..6e181a9 100644
--- a/extra/yassl/src/handshake.cpp
+++ b/extra/yassl/src/handshake.cpp
@@ -788,6 +788,16 @@ int DoProcessReply(SSL& ssl)
needHdr = true;
else {
buffer >> hdr;
+ /*
+ According to RFC 4346 (see "7.4.1.3. Server Hello"), the Server Hello
+ packet needs to specify the highest supported TLS version, but not
+ higher than what client requests. YaSSL highest supported version is
+ TLSv1.1 (=3.2) - if the client requests a higher version, downgrade it
+ here to 3.2.
+ See also Appendix E of RFC 5246 (TLS 1.2)
+ */
+ if (hdr.version_.major_ == 3 && hdr.version_.minor_ > 2)
+ hdr.version_.minor_ = 2;
ssl.verifyState(hdr);
}
diff --git a/include/ssl_compat.h b/include/ssl_compat.h
new file mode 100644
index 0000000..b0e3ed4
--- /dev/null
+++ b/include/ssl_compat.h
@@ -0,0 +1,75 @@
+/*
+ Copyright (c) 2016, 2017 MariaDB Corporation
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include <openssl/opensslv.h>
+
+/* OpenSSL version specific definitions */
+#if !defined(HAVE_YASSL) && defined(OPENSSL_VERSION_NUMBER)
+
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)
+#define HAVE_X509_check_host 1
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+#define HAVE_OPENSSL11 1
+#define ERR_remove_state(X) ERR_clear_error()
+#define EVP_MD_CTX_cleanup(X) EVP_MD_CTX_reset(X)
+#define EVP_CIPHER_CTX_SIZE 168
+#define EVP_MD_CTX_SIZE 48
+#undef EVP_MD_CTX_init
+#define EVP_MD_CTX_init(X) do { bzero((X), EVP_MD_CTX_SIZE); EVP_MD_CTX_reset(X); } while(0)
+#undef EVP_CIPHER_CTX_init
+#define EVP_CIPHER_CTX_init(X) do { bzero((X), EVP_CIPHER_CTX_SIZE); EVP_CIPHER_CTX_reset(X); } while(0)
+
+#else
+#define HAVE_OPENSSL10 1
+/*
+ Unfortunately RAND_bytes manual page does not provide any guarantees
+ in relation to blocking behavior. Here we explicitly use SSLeay random
+ instead of whatever random engine is currently set in OpenSSL. That way
+ we are guaranteed to have a non-blocking random.
+*/
+#define RAND_OpenSSL() RAND_SSLeay()
+
+#ifdef HAVE_ERR_remove_thread_state
+#define ERR_remove_state(X) ERR_remove_thread_state(NULL)
+#endif /* HAVE_ERR_remove_thread_state */
+
+#endif /* HAVE_OPENSSL11 */
+
+#elif defined(HAVE_YASSL)
+#define BN_free(X) do { } while(0)
+#endif /* !defined(HAVE_YASSL) */
+
+#ifndef HAVE_OPENSSL11
+#define ASN1_STRING_get0_data(X) ASN1_STRING_data(X)
+#define OPENSSL_init_ssl(X,Y) SSL_library_init()
+#define DH_set0_pqg(D,P,Q,G) ((D)->p= (P), (D)->g= (G))
+#define EVP_CIPHER_CTX_buf_noconst(ctx) ((ctx)->buf)
+#define EVP_CIPHER_CTX_encrypting(ctx) ((ctx)->encrypt)
+#define EVP_CIPHER_CTX_SIZE sizeof(EVP_CIPHER_CTX)
+#define EVP_MD_CTX_SIZE sizeof(EVP_MD_CTX)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+int check_openssl_compatibility();
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/violite.h b/include/violite.h
index a7165ca..572d474 100644
--- a/include/violite.h
+++ b/include/violite.h
@@ -123,13 +123,6 @@ int vio_getnameinfo(const struct sockaddr *sa,
int flags);
#ifdef HAVE_OPENSSL
-#include <openssl/opensslv.h>
-#if OPENSSL_VERSION_NUMBER < 0x0090700f
-#define DES_cblock des_cblock
-#define DES_key_schedule des_key_schedule
-#define DES_set_key_unchecked(k,ks) des_set_key_unchecked((k),*(ks))
-#define DES_ede3_cbc_encrypt(i,o,l,k1,k2,k3,iv,e) des_ede3_cbc_encrypt((i),(o),(l),*(k1),*(k2),*(k3),(iv),(e))
-#endif
/* apple deprecated openssl in MacOSX Lion */
#ifdef __APPLE__
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
@@ -146,14 +139,10 @@ typedef my_socket YASSL_SOCKET_T;
#include <openssl/ssl.h>
#include <openssl/err.h>
-#ifdef HAVE_ERR_remove_thread_state
-#define ERR_remove_state(X) ERR_remove_thread_state(NULL)
-#endif
-
enum enum_ssl_init_error
{
- SSL_INITERR_NOERROR= 0, SSL_INITERR_CERT, SSL_INITERR_KEY,
- SSL_INITERR_NOMATCH, SSL_INITERR_BAD_PATHS, SSL_INITERR_CIPHERS,
+ SSL_INITERR_NOERROR= 0, SSL_INITERR_CERT, SSL_INITERR_KEY,
+ SSL_INITERR_NOMATCH, SSL_INITERR_BAD_PATHS, SSL_INITERR_CIPHERS,
SSL_INITERR_MEMFAIL, SSL_INITERR_DH, SSL_INITERR_LASTERR
};
const char* sslGetErrString(enum enum_ssl_init_error err);
diff --git a/mysql-test/include/require_openssl_client.inc b/mysql-test/include/require_openssl_client.inc
new file mode 100644
index 0000000..9b19960
--- /dev/null
+++ b/mysql-test/include/require_openssl_client.inc
@@ -0,0 +1,5 @@
+if ($CLIENT_TLS_LIBRARY != "OpenSSL") {
+ if ($CLIENT_TLS_LIBRARY != "LibreSSL") {
+ skip "Test requires Connector/C with OpenSSL library";
+ }
+}
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index eaec51b..1b28469 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -2301,6 +2301,11 @@ sub environment_setup {
$ENV{'MYSQL_PLUGIN'}= $exe_mysql_plugin;
$ENV{'MYSQL_EMBEDDED'}= $exe_mysql_embedded;
+ my $client_config_exe=
+ native_path("$bindir/libmariadb/mariadb_config$opt_vs_config/mariadb_config");
+ my $tls_info= `$client_config_exe --tlsinfo`;
+ ($ENV{CLIENT_TLS_LIBRARY},$ENV{CLIENT_TLS_LIBRARY_VERSION})=
+ split(/ /, $tls_info, 2);
my $exe_mysqld= find_mysqld($basedir);
$ENV{'MYSQLD'}= $exe_mysqld;
my $extra_opts= join (" ", @opt_extra_mysqld_opt);
diff --git a/mysql-test/r/openssl_6975,tlsv10.result b/mysql-test/r/openssl_6975,tlsv10.result
index 7a4465f..202e7f4 100644
--- a/mysql-test/r/openssl_6975,tlsv10.result
+++ b/mysql-test/r/openssl_6975,tlsv10.result
@@ -3,11 +3,11 @@ grant select on test.* to ssl_sslv3@localhost require cipher "AES128-SHA";
create user ssl_tls12@localhost;
grant select on test.* to ssl_tls12@localhost require cipher "AES128-SHA256";
TLS1.2 ciphers: user is ok with any cipher
-ERROR 2026 (HY000): SSL connection error: error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
-ERROR 2026 (HY000): SSL connection error: error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
+ERROR 2026 (HY000): SSL connection error: sslv3 alert handshake failure
+ERROR 2026 (HY000): SSL connection error: sslv3 alert handshake failure
TLS1.2 ciphers: user requires SSLv3 cipher AES128-SHA
-ERROR 2026 (HY000): SSL connection error: error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
-ERROR 2026 (HY000): SSL connection error: error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
+ERROR 2026 (HY000): SSL connection error: sslv3 alert handshake failure
+ERROR 2026 (HY000): SSL connection error: sslv3 alert handshake failure
TLS1.2 ciphers: user requires TLSv1.2 cipher AES128-SHA256
ERROR 2026 (HY000): SSL connection error: error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
ERROR 2026 (HY000): SSL connection error: error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
diff --git a/mysql-test/t/openssl_6975.test b/mysql-test/t/openssl_6975.test
index 49889a3..6a82d01 100644
--- a/mysql-test/t/openssl_6975.test
+++ b/mysql-test/t/openssl_6975.test
@@ -4,6 +4,7 @@
# test SSLv3 and TLSv1.2 ciphers when OpenSSL is restricted to SSLv3 or TLSv1.2
#
source include/have_ssl_communication.inc;
+source include/require_openssl_client.inc;
# this is OpenSSL test.
diff --git a/mysql-test/t/ssl_7937.test b/mysql-test/t/ssl_7937.test
index d593b9d..a764579 100644
--- a/mysql-test/t/ssl_7937.test
+++ b/mysql-test/t/ssl_7937.test
@@ -26,6 +26,7 @@ create procedure have_ssl()
# we fake the test result for yassl
let yassl=`select variable_value='Unknown' from information_schema.session_status where variable_name='Ssl_session_cache_mode'`;
if (!$yassl) {
+ --replace_result "self signed certificate in certificate chain" "Failed to verify the server certificate" "Error in the certificate." "Failed to verify the server certificate"
--exec $MYSQL --ssl --ssl-verify-server-cert -e "call test.have_ssl()" 2>&1
}
if ($yassl) {
diff --git a/mysql-test/t/ssl_8k_key.test b/mysql-test/t/ssl_8k_key.test
index 27cffdc..9d5b382 100644
--- a/mysql-test/t/ssl_8k_key.test
+++ b/mysql-test/t/ssl_8k_key.test
@@ -1,5 +1,5 @@
-# This test should work in embedded server after we fix mysqltest
--- source include/not_embedded.inc
+# schannel does not support keys longer than 4k
+-- source include/not_windows.inc
-- source include/have_ssl_communication.inc
#
diff --git a/mysys_ssl/CMakeLists.txt b/mysys_ssl/CMakeLists.txt
index 4f6f745..f8a767e 100644
--- a/mysys_ssl/CMakeLists.txt
+++ b/mysys_ssl/CMakeLists.txt
@@ -28,6 +28,7 @@ SET(MYSYS_SSL_HIDDEN_SOURCES
my_sha384.cc
my_sha512.cc
my_md5.cc
+ openssl.c
)
SET(MYSYS_SSL_SOURCES
diff --git a/mysys_ssl/my_crypt.cc b/mysys_ssl/my_crypt.cc
index 4393394..da60a10 100644
--- a/mysys_ssl/my_crypt.cc
+++ b/mysys_ssl/my_crypt.cc
@@ -1,6 +1,6 @@
/*
Copyright (c) 2014 Google Inc.
- Copyright (c) 2014, 2015 MariaDB Corporation
+ Copyright (c) 2014, 2017 MariaDB Corporation
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -17,7 +17,6 @@
#include <my_global.h>
#include <string.h>
-#include <my_crypt.h>
#ifdef HAVE_YASSL
#include "yassl.cc"
@@ -28,42 +27,53 @@
#include <openssl/err.h>
#include <openssl/rand.h>
-#ifdef HAVE_ERR_remove_thread_state
-#define ERR_remove_state(X) ERR_remove_thread_state(NULL)
+#include <openssl/rand.h>
#endif
-#endif
+#include <my_crypt.h>
+#include <ssl_compat.h>
class MyCTX
{
public:
- EVP_CIPHER_CTX ctx;
- MyCTX() { EVP_CIPHER_CTX_init(&ctx); }
- virtual ~MyCTX() { EVP_CIPHER_CTX_cleanup(&ctx); ERR_remove_state(0); }
+ char ctx_buf[EVP_CIPHER_CTX_SIZE];
+ EVP_CIPHER_CTX *ctx;
+
+ MyCTX()
+ {
+ ctx= (EVP_CIPHER_CTX *)ctx_buf;
+ EVP_CIPHER_CTX_init(ctx);
+ }
+ virtual ~MyCTX()
+ {
+ EVP_CIPHER_CTX_cleanup(ctx);
+ ERR_remove_state(0);
+ }
virtual int init(const EVP_CIPHER *cipher, int encrypt, const uchar *key,
uint klen, const uchar *iv, uint ivlen)
{
+ compile_time_assert(MY_AES_CTX_SIZE >= sizeof(MyCTX));
if (unlikely(!cipher))
return MY_AES_BAD_KEYSIZE;
- if (!EVP_CipherInit_ex(&ctx, cipher, NULL, key, iv, encrypt))
+ if (!EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, encrypt))
return MY_AES_OPENSSL_ERROR;
- DBUG_ASSERT(EVP_CIPHER_CTX_key_length(&ctx) == (int)klen);
- DBUG_ASSERT(EVP_CIPHER_CTX_iv_length(&ctx) <= (int)ivlen);
+ DBUG_ASSERT(EVP_CIPHER_CTX_key_length(ctx) == (int)klen);
+ DBUG_ASSERT(EVP_CIPHER_CTX_iv_length(ctx) <= (int)ivlen);
return MY_AES_OK;
}
virtual int update(const uchar *src, uint slen, uchar *dst, uint *dlen)
{
- if (!EVP_CipherUpdate(&ctx, dst, (int*)dlen, src, slen))
+ if (!EVP_CipherUpdate(ctx, dst, (int*)dlen, src, slen))
return MY_AES_OPENSSL_ERROR;
return MY_AES_OK;
}
virtual int finish(uchar *dst, uint *dlen)
{
- if (!EVP_CipherFinal_ex(&ctx, dst, (int*)dlen))
+ if (!EVP_CipherFinal_ex(ctx, dst, (int*)dlen))
return MY_AES_BAD_DATA;
return MY_AES_OK;
}
@@ -73,7 +83,8 @@ class MyCTX_nopad : public MyCTX
{
public:
const uchar *key;
- int klen;
+ uint klen, buf_len;
+ uchar oiv[MY_AES_BLOCK_SIZE];
MyCTX_nopad() : MyCTX() { }
~MyCTX_nopad() { }
@@ -84,32 +95,48 @@ class MyCTX_nopad : public MyCTX
compile_time_assert(MY_AES_CTX_SIZE >= sizeof(MyCTX_nopad));
this->key= key;
this->klen= klen;
+ this->buf_len= 0;
+ memcpy(oiv, iv, ivlen);
+ DBUG_ASSERT(ivlen == 0 || ivlen == sizeof(oiv));
+
int res= MyCTX::init(cipher, encrypt, key, klen, iv, ivlen);
- memcpy(ctx.oiv, iv, ivlen); // in ECB mode OpenSSL doesn't do that itself
- EVP_CIPHER_CTX_set_padding(&ctx, 0);
+
+ EVP_CIPHER_CTX_set_padding(ctx, 0);
return res;
}
+ int update(const uchar *src, uint slen, uchar *dst, uint *dlen)
+ {
+ buf_len+= slen;
+ return MyCTX::update(src, slen, dst, dlen);
+ }
+
int finish(uchar *dst, uint *dlen)
{
- if (ctx.buf_len)
+ buf_len %= MY_AES_BLOCK_SIZE;
+ if (buf_len)
{
+ uchar *buf= EVP_CIPHER_CTX_buf_noconst(ctx);
/*
Not much we can do, block ciphers cannot encrypt data that aren't
a multiple of the block length. At least not without padding.
Let's do something CTR-like for the last partial block.
+
+ NOTE this assumes that there are only buf_len bytes in the buf.
+ If OpenSSL will change that, we'll need to change the implementation
+ of this class too.
*/
uchar mask[MY_AES_BLOCK_SIZE];
uint mlen;
my_aes_crypt(MY_AES_ECB, ENCRYPTION_FLAG_ENCRYPT | ENCRYPTION_FLAG_NOPAD,
- ctx.oiv, sizeof(mask), mask, &mlen, key, klen, 0, 0);
+ oiv, sizeof(mask), mask, &mlen, key, klen, 0, 0);
DBUG_ASSERT(mlen == sizeof(mask));
- for (int i=0; i < ctx.buf_len; i++)
- dst[i]= ctx.buf[i] ^ mask[i];
+ for (uint i=0; i < buf_len; i++)
+ dst[i]= buf[i] ^ mask[i];
}
- *dlen= ctx.buf_len;
+ *dlen= buf_len;
return MY_AES_OK;
}
};
@@ -153,7 +180,7 @@ class MyCTX_gcm : public MyCTX
{
compile_time_assert(MY_AES_CTX_SIZE >= sizeof(MyCTX_gcm));
int res= MyCTX::init(cipher, encrypt, key, klen, iv, ivlen);
- int real_ivlen= EVP_CIPHER_CTX_iv_length(&ctx);
+ int real_ivlen= EVP_CIPHER_CTX_iv_length(ctx);
aad= iv + real_ivlen;
aadlen= ivlen - real_ivlen;
return res;
@@ -167,15 +194,15 @@ class MyCTX_gcm : public MyCTX
before decrypting the data. it can encrypt data piecewise, like, first
half, then the second half, but it must decrypt all at once
*/
- if (!ctx.encrypt)
+ if (!EVP_CIPHER_CTX_encrypting(ctx))
{
slen-= MY_AES_BLOCK_SIZE;
- if(!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_TAG, MY_AES_BLOCK_SIZE,
+ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, MY_AES_BLOCK_SIZE,
(void*)(src + slen)))
return MY_AES_OPENSSL_ERROR;
}
int unused;
- if (aadlen && !EVP_CipherUpdate(&ctx, NULL, &unused, aad, aadlen))
+ if (aadlen && !EVP_CipherUpdate(ctx, NULL, &unused, aad, aadlen))
return MY_AES_OPENSSL_ERROR;
aadlen= 0;
return MyCTX::update(src, slen, dst, dlen);
@@ -184,13 +211,13 @@ class MyCTX_gcm : public MyCTX
int finish(uchar *dst, uint *dlen)
{
int fin;
- if (!EVP_CipherFinal_ex(&ctx, dst, &fin))
+ if (!EVP_CipherFinal_ex(ctx, dst, &fin))
return MY_AES_BAD_DATA;
DBUG_ASSERT(fin == 0);
- if (ctx.encrypt)
+ if (EVP_CIPHER_CTX_encrypting(ctx))
{
- if(!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, MY_AES_BLOCK_SIZE, dst))
+ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, MY_AES_BLOCK_SIZE, dst))
return MY_AES_OPENSSL_ERROR;
*dlen= MY_AES_BLOCK_SIZE;
}
@@ -258,12 +285,15 @@ int my_aes_crypt(enum my_aes_mode mode, int flags,
{
void *ctx= alloca(MY_AES_CTX_SIZE);
int res1, res2;
- uint d1, d2;
+ uint d1= 0, d2;
if ((res1= my_aes_crypt_init(ctx, mode, flags, key, klen, iv, ivlen)))
return res1;
res1= my_aes_crypt_update(ctx, src, slen, dst, &d1);
res2= my_aes_crypt_finish(ctx, dst + d1, &d2);
- *dlen= d1 + d2;
+ if (res1 || res2)
+ ERR_remove_state(0); /* in case of failure clear error queue */
+ else
+ *dlen= d1 + d2;
return res1 ? res1 : res2;
}
diff --git a/mysys_ssl/my_md5.cc b/mysys_ssl/my_md5.cc
index 7139ea9..0105082 100644
--- a/mysys_ssl/my_md5.cc
+++ b/mysys_ssl/my_md5.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2012, Oracle and/or its affiliates.
- Copyright (c) 2014, SkySQL Ab.
+ Copyright (c) 2017, MariaDB Corporation
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -29,38 +29,31 @@
#if defined(HAVE_YASSL)
#include "md5.hpp"
+#include <ssl_compat.h>
-typedef TaoCrypt::MD5 MD5_CONTEXT;
+typedef TaoCrypt::MD5 EVP_MD_CTX;
-static void md5_init(MD5_CONTEXT *context)
+static void md5_init(EVP_MD_CTX *context)
{
- context= new(context) MD5_CONTEXT;
+ context= new(context) EVP_MD_CTX;
context->Init();
}
-/*
- this is a variant of md5_init to be used in this file only.
- does nothing for yassl, because the context's constructor was called automatically.
-*/
-static void md5_init_fast(MD5_CONTEXT *context)
-{
-}
-
-static void md5_input(MD5_CONTEXT *context, const uchar *buf, unsigned len)
+static void md5_input(EVP_MD_CTX *context, const uchar *buf, unsigned len)
{
context->Update((const TaoCrypt::byte *) buf, len);
}
-static void md5_result(MD5_CONTEXT *context, uchar digest[MD5_HASH_SIZE])
+static void md5_result(EVP_MD_CTX *context, uchar digest[MD5_HASH_SIZE])
{
context->Final((TaoCrypt::byte *) digest);
}
#elif defined(HAVE_OPENSSL)
#include <openssl/evp.h>
-typedef EVP_MD_CTX MD5_CONTEXT;
+#include <ssl_compat.h>
-static void md5_init(MD5_CONTEXT *context)
+static void md5_init(EVP_MD_CTX *context)
{
EVP_MD_CTX_init(context);
#ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
@@ -70,17 +63,12 @@ static void md5_init(MD5_CONTEXT *context)
EVP_DigestInit_ex(context, EVP_md5(), NULL);
}
-static void md5_init_fast(MD5_CONTEXT *context)
-{
- md5_init(context);
-}
-
-static void md5_input(MD5_CONTEXT *context, const uchar *buf, unsigned len)
+static void md5_input(EVP_MD_CTX *context, const uchar *buf, unsigned len)
{
EVP_DigestUpdate(context, buf, len);
}
-static void md5_result(MD5_CONTEXT *context, uchar digest[MD5_HASH_SIZE])
+static void md5_result(EVP_MD_CTX *context, uchar digest[MD5_HASH_SIZE])
{
EVP_DigestFinal_ex(context, digest, NULL);
EVP_MD_CTX_cleanup(context);
@@ -99,58 +87,58 @@ static void md5_result(MD5_CONTEXT *context, uchar digest[MD5_HASH_SIZE])
*/
void my_md5(uchar *digest, const char *buf, size_t len)
{
- MD5_CONTEXT md5_context;
-
- md5_init_fast(&md5_context);
- md5_input(&md5_context, (const uchar *)buf, len);
- md5_result(&md5_context, digest);
+ char ctx_buf[EVP_MD_CTX_SIZE];
+ EVP_MD_CTX * const ctx= (EVP_MD_CTX*)ctx_buf;
+ md5_init(ctx);
+ md5_input(ctx, (const uchar *)buf, len);
+ md5_result(ctx, digest);
}
/**
Wrapper function to compute MD5 message digest for
- two messages in order to emulate md5(msg1, msg2).
+ many messages, concatenated.
@param digest [out] Computed MD5 digest
@param buf1 [in] First message
@param len1 [in] Length of first message
- @param buf2 [in] Second message
- @param len2 [in] Length of second message
+ ...
+ @param bufN [in] NULL terminates the list of buf,len pairs.
@return void
*/
void my_md5_multi(uchar *digest, ...)
{
va_list args;
- va_start(args, digest);
-
- MD5_CONTEXT md5_context;
const uchar *str;
+ char ctx_buf[EVP_MD_CTX_SIZE];
+ EVP_MD_CTX * const ctx= (EVP_MD_CTX*)ctx_buf;
+ va_start(args, digest);
- md5_init_fast(&md5_context);
+ md5_init(ctx);
for (str= va_arg(args, const uchar*); str; str= va_arg(args, const uchar*))
- md5_input(&md5_context, str, va_arg(args, size_t));
+ md5_input(ctx, str, va_arg(args, size_t));
- md5_result(&md5_context, digest);
+ md5_result(ctx, digest);
va_end(args);
}
size_t my_md5_context_size()
{
- return sizeof(MD5_CONTEXT);
+ return EVP_MD_CTX_SIZE;
}
void my_md5_init(void *context)
{
- md5_init((MD5_CONTEXT *)context);
+ md5_init((EVP_MD_CTX *)context);
}
void my_md5_input(void *context, const uchar *buf, size_t len)
{
- md5_input((MD5_CONTEXT *)context, buf, len);
+ md5_input((EVP_MD_CTX *)context, buf, len);
}
void my_md5_result(void *context, uchar *digest)
{
- md5_result((MD5_CONTEXT *)context, digest);
+ md5_result((EVP_MD_CTX *)context, digest);
}
diff --git a/mysys_ssl/openssl.c b/mysys_ssl/openssl.c
new file mode 100644
index 0000000..a3f1ca2
--- /dev/null
+++ b/mysys_ssl/openssl.c
@@ -0,0 +1,71 @@
+/*
+ Copyright (c) 2017, MariaDB Corporation.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include <my_global.h>
+#include <ssl_compat.h>
+
+#ifdef HAVE_YASSL
+
+int check_openssl_compatibility()
+{
+ return 0;
+}
+#else
+#include <openssl/evp.h>
+
+#ifdef HAVE_OPENSSL11
+typedef void *(*CRYPTO_malloc_t)(size_t, const char *, int);
+#endif
+
+#ifdef HAVE_OPENSSL10
+typedef void *(*CRYPTO_malloc_t)(size_t);
+#define CRYPTO_malloc malloc
+#define CRYPTO_realloc realloc
+#define CRYPTO_free free
+#endif
+
+static uint allocated_size, allocated_count;
+
+static void *coc_malloc(size_t size)
+{
+ allocated_size+= size;
+ allocated_count++;
+ return malloc(size);
+}
+
+int check_openssl_compatibility()
+{
+ EVP_CIPHER_CTX *evp_ctx;
+ EVP_MD_CTX *md5_ctx;
+
+ CRYPTO_set_mem_functions((CRYPTO_malloc_t)coc_malloc, CRYPTO_realloc, CRYPTO_free);
+
+ allocated_size= allocated_count= 0;
+ evp_ctx= EVP_CIPHER_CTX_new();
+ EVP_CIPHER_CTX_free(evp_ctx);
+ if (allocated_count != 1 || allocated_size > EVP_CIPHER_CTX_SIZE)
+ return 1;
+
+ allocated_size= allocated_count= 0;
+ md5_ctx= EVP_MD_CTX_create();
+ EVP_MD_CTX_destroy(md5_ctx);
+ if (allocated_count != 1 || allocated_size > EVP_MD_CTX_SIZE)
+ return 1;
+
+ CRYPTO_set_mem_functions(CRYPTO_malloc, CRYPTO_realloc, CRYPTO_free);
+ return 0;
+}
+#endif
diff --git a/mysys_ssl/yassl.cc b/mysys_ssl/yassl.cc
index e9f8e65..268589d 100644
--- a/mysys_ssl/yassl.cc
+++ b/mysys_ssl/yassl.cc
@@ -45,7 +45,6 @@ typedef struct
int buf_len;
int final_used;
uchar tao_buf[sizeof(TaoCrypt::AES)]; // TaoCrypt::AES object
- uchar oiv[TaoCrypt::AES::BLOCK_SIZE]; // original IV
uchar buf[TaoCrypt::AES::BLOCK_SIZE]; // last partial input block
uchar final[TaoCrypt::AES::BLOCK_SIZE]; // last decrypted (output) block
} EVP_CIPHER_CTX;
@@ -98,10 +97,7 @@ static int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
: TaoCrypt::DECRYPTION, cipher->mode);
TAO(ctx)->SetKey(key, cipher->key_len);
if (iv)
- {
TAO(ctx)->SetIV(iv);
- memcpy(ctx->oiv, iv, TaoCrypt::AES::BLOCK_SIZE);
- }
ctx->encrypt= enc;
ctx->key_len= cipher->key_len;
ctx->flags|= cipher->mode == TaoCrypt::CBC ? EVP_CIPH_CBC_MODE : EVP_CIPH_ECB_MODE;
diff --git a/sql-common/client.c b/sql-common/client.c
index da18a0f..e3280a1 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -105,6 +105,7 @@ my_bool net_flush(NET *net);
#endif
#include "client_settings.h"
+#include <ssl_compat.h>
#include <sql_common.h>
#include <mysql/client_plugin.h>
#include <my_context.h>
@@ -1770,9 +1771,8 @@ mysql_get_ssl_cipher(MYSQL *mysql __attribute__((unused)))
#if defined(HAVE_OPENSSL)
-#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(HAVE_YASSL)
+#ifdef HAVE_X509_check_host
#include <openssl/x509v3.h>
-#define HAVE_X509_check_host
#endif
static int ssl_verify_server_cert(Vio *vio, const char* server_hostname, const char **errptr)
@@ -1844,7 +1844,7 @@ static int ssl_verify_server_cert(Vio *vio, const char* server_hostname, const c
goto error;
}
- cn= (char *) ASN1_STRING_data(cn_asn1);
+ cn= (char *) ASN1_STRING_get0_data(cn_asn1);
if ((size_t)ASN1_STRING_length(cn_asn1) != strlen(cn))
{
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 0de9d7a..3a92192 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -338,9 +338,13 @@ static PSI_thread_key key_thread_handle_con_sockets;
static PSI_thread_key key_thread_handle_shutdown;
#endif /* __WIN__ */
-#if defined (HAVE_OPENSSL) && !defined(HAVE_YASSL)
+#ifdef HAVE_OPENSSL
+#include <ssl_compat.h>
+
+#ifdef HAVE_OPENSSL10
static PSI_rwlock_key key_rwlock_openssl;
#endif
+#endif
#endif /* HAVE_PSI_INTERFACE */
#ifdef HAVE_NPTL
@@ -987,7 +991,7 @@ PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger,
static PSI_rwlock_info all_server_rwlocks[]=
{
-#if defined (HAVE_OPENSSL) && !defined(HAVE_YASSL)
+#ifdef HAVE_OPENSSL10
{ &key_rwlock_openssl, "CRYPTO_dynlock_value::lock", 0},
#endif
{ &key_rwlock_LOCK_grant, "LOCK_grant", PSI_FLAG_GLOBAL},
@@ -1457,7 +1461,7 @@ scheduler_functions *thread_scheduler= &thread_scheduler_struct,
#ifdef HAVE_OPENSSL
#include <openssl/crypto.h>
-#ifndef HAVE_YASSL
+#ifdef HAVE_OPENSSL10
typedef struct CRYPTO_dynlock_value
{
mysql_rwlock_t lock;
@@ -1468,7 +1472,7 @@ static openssl_lock_t *openssl_dynlock_create(const char *, int);
static void openssl_dynlock_destroy(openssl_lock_t *, const char *, int);
static void openssl_lock_function(int, int, const char *, int);
static void openssl_lock(int, openssl_lock_t *, const char *, int);
-#endif
+#endif /* HAVE_OPENSSL10 */
char *des_key_file;
#ifndef EMBEDDED_LIBRARY
struct st_VioSSLFd *ssl_acceptor_fd;
@@ -2244,11 +2248,11 @@ static void clean_up_mutexes()
mysql_mutex_destroy(&LOCK_global_index_stats);
#ifdef HAVE_OPENSSL
mysql_mutex_destroy(&LOCK_des_key_file);
-#ifndef HAVE_YASSL
+#ifdef HAVE_OPENSSL10
for (int i= 0; i < CRYPTO_num_locks(); ++i)
mysql_rwlock_destroy(&openssl_stdlocks[i].lock);
OPENSSL_free(openssl_stdlocks);
-#endif /* HAVE_YASSL */
+#endif /* HAVE_OPENSSL10 */
#endif /* HAVE_OPENSSL */
#ifdef HAVE_REPLICATION
mysql_mutex_destroy(&LOCK_rpl_status);
@@ -4038,6 +4042,14 @@ static int init_common_variables()
return 1;
}
+#ifdef HAVE_OPENSSL
+ if (check_openssl_compatibility())
+ {
+ sql_print_error("Incompatible OpenSSL version. Cannot continue...");
+ return 1;
+ }
+#endif
+
if (init_thread_environment() ||
mysql_init_variables())
return 1;
@@ -4584,7 +4596,7 @@ static int init_thread_environment()
#ifdef HAVE_OPENSSL
mysql_mutex_init(key_LOCK_des_key_file,
&LOCK_des_key_file, MY_MUTEX_INIT_FAST);
-#ifndef HAVE_YASSL
+#ifdef HAVE_OPENSSL10
openssl_stdlocks= (openssl_lock_t*) OPENSSL_malloc(CRYPTO_num_locks() *
sizeof(openssl_lock_t));
for (int i= 0; i < CRYPTO_num_locks(); ++i)
@@ -4593,8 +4605,8 @@ static int init_thread_environment()
CRYPTO_set_dynlock_destroy_callback(openssl_dynlock_destroy);
CRYPTO_set_dynlock_lock_callback(openssl_lock);
CRYPTO_set_locking_callback(openssl_lock_function);
-#endif
-#endif
+#endif /* HAVE_OPENSSL10 */
+#endif /* HAVE_OPENSSL */
mysql_rwlock_init(key_rwlock_LOCK_sys_init_connect, &LOCK_sys_init_connect);
mysql_rwlock_init(key_rwlock_LOCK_sys_init_slave, &LOCK_sys_init_slave);
mysql_rwlock_init(key_rwlock_LOCK_grant, &LOCK_grant);
@@ -4627,7 +4639,7 @@ static int init_thread_environment()
}
-#if defined(HAVE_OPENSSL) && !defined(HAVE_YASSL)
+#ifdef HAVE_OPENSSL10
static openssl_lock_t *openssl_dynlock_create(const char *file, int line)
{
openssl_lock_t *lock= new openssl_lock_t;
@@ -4687,8 +4699,7 @@ static void openssl_lock(int mode, openssl_lock_t *lock, const char *file,
abort();
}
}
-#endif /* HAVE_OPENSSL */
-
+#endif /* HAVE_OPENSSL10 */
static void init_ssl()
{
diff --git a/sql/slave.cc b/sql/slave.cc
index da394ff..2096ed1 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -40,6 +40,7 @@
#include <my_dir.h>
#include <sql_common.h>
#include <errmsg.h>
+#include <ssl_compat.h>
#include <mysqld_error.h>
#include <mysys_err.h>
#include "rpl_handler.h"
@@ -60,7 +61,6 @@
#include "debug_sync.h"
#include "rpl_parallel.h"
-
#define FLAGSTR(V,F) ((V)&(F)?#F" ":"")
#define MAX_SLAVE_RETRY_PAUSE 5
@@ -4506,9 +4506,7 @@ log space");
DBUG_LEAVE; // Must match DBUG_ENTER()
my_thread_end();
-#ifdef HAVE_OPENSSL
ERR_remove_state(0);
-#endif
pthread_exit(0);
return 0; // Avoid compiler warnings
}
@@ -5167,9 +5165,7 @@ pthread_handler_t handle_slave_sql(void *arg)
DBUG_LEAVE; // Must match DBUG_ENTER()
my_thread_end();
-#ifdef HAVE_OPENSSL
ERR_remove_state(0);
-#endif
pthread_exit(0);
return 0; // Avoid compiler warnings
}
diff --git a/vio/vio.c b/vio/vio.c
index e3bc8ca..44d0609 100644
--- a/vio/vio.c
+++ b/vio/vio.c
@@ -22,6 +22,7 @@
*/
#include "vio_priv.h"
+#include "ssl_compat.h"
#ifdef _WIN32
diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c
index 52b624d..71ef287 100644
--- a/vio/viosslfactories.c
+++ b/vio/viosslfactories.c
@@ -15,6 +15,7 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#include "vio_priv.h"
+#include <ssl_compat.h>
#ifdef HAVE_OPENSSL
#ifndef HAVE_YASSL
@@ -26,49 +27,56 @@ static my_bool ssl_algorithms_added = FALSE;
static my_bool ssl_error_strings_loaded= FALSE;
/* the function below was generated with "openssl dhparam -2 -C 2048" */
+
static
DH *get_dh2048()
{
- static unsigned char dh2048_p[]={
- 0xA1,0xBB,0x7C,0x20,0xC5,0x5B,0xC0,0x7B,0x21,0x8B,0xD6,0xA8,
- 0x15,0xFC,0x3B,0xBA,0xAB,0x9F,0xDF,0x68,0xC4,0x79,0x78,0x0D,
- 0xC1,0x12,0x64,0xE4,0x15,0xC9,0x66,0xDB,0xF6,0xCB,0xB3,0x39,
- 0x02,0x5B,0x78,0x62,0xFB,0x09,0xAE,0x09,0x6B,0xDD,0xD4,0x5D,
- 0x97,0xBC,0xDC,0x7F,0xE6,0xD6,0xF1,0xCB,0xF5,0xEB,0xDA,0xA7,
- 0x2E,0x5A,0x43,0x2B,0xE9,0x40,0xE2,0x85,0x00,0x1C,0xC0,0x0A,
- 0x98,0x77,0xA9,0x31,0xDE,0x0B,0x75,0x4D,0x1E,0x1F,0x16,0x83,
- 0xCA,0xDE,0xBD,0x21,0xFC,0xC1,0x82,0x37,0x36,0x33,0x0B,0x66,
- 0x06,0x3C,0xF3,0xAF,0x21,0x57,0x57,0x80,0xF6,0x94,0x1B,0xA9,
- 0xD4,0xF6,0x8F,0x18,0x62,0x0E,0xC4,0x22,0xF9,0x5B,0x62,0xCC,
- 0x3F,0x19,0x95,0xCF,0x4B,0x00,0xA6,0x6C,0x0B,0xAF,0x9F,0xD5,
- 0xFA,0x3D,0x6D,0xDA,0x30,0x83,0x07,0x91,0xAC,0x15,0xFF,0x8F,
- 0x59,0x54,0xEA,0x25,0xBC,0x4E,0xEB,0x6A,0x54,0xDF,0x75,0x09,
- 0x72,0x0F,0xEF,0x23,0x70,0xE0,0xA8,0x04,0xEA,0xFF,0x90,0x54,
- 0xCD,0x84,0x18,0xC0,0x75,0x91,0x99,0x0F,0xA1,0x78,0x0C,0x07,
- 0xB7,0xC5,0xDE,0x55,0x06,0x7B,0x95,0x68,0x2C,0x33,0x39,0xBC,
- 0x2C,0xD0,0x6D,0xDD,0xFA,0xDC,0xB5,0x8F,0x82,0x39,0xF8,0x67,
- 0x44,0xF1,0xD8,0xF7,0x78,0x11,0x9A,0x77,0x9B,0x53,0x47,0xD6,
- 0x2B,0x5D,0x67,0xB8,0xB7,0xBC,0xC1,0xD7,0x79,0x62,0x15,0xC2,
- 0xC5,0x83,0x97,0xA7,0xF8,0xB4,0x9C,0xF6,0x8F,0x9A,0xC7,0xDA,
- 0x1B,0xBB,0x87,0x07,0xA7,0x71,0xAD,0xB2,0x8A,0x50,0xF8,0x26,
- 0x12,0xB7,0x3E,0x0B,
- };
- static unsigned char dh2048_g[]={
- 0x02,
- };
- DH *dh;
-
- if ((dh=DH_new()) == NULL) return(NULL);
- dh->p=BN_bin2bn(dh2048_p,sizeof(dh2048_p),NULL);
- dh->g=BN_bin2bn(dh2048_g,sizeof(dh2048_g),NULL);
- if ((dh->p == NULL) || (dh->g == NULL))
- { DH_free(dh); return(NULL); }
- return(dh);
+ static unsigned char dhp_2048[] = {
+ 0xA1,0xBB,0x7C,0x20,0xC5,0x5B,0xC0,0x7B,0x21,0x8B,0xD6,0xA8,
+ 0x15,0xFC,0x3B,0xBA,0xAB,0x9F,0xDF,0x68,0xC4,0x79,0x78,0x0D,
+ 0xC1,0x12,0x64,0xE4,0x15,0xC9,0x66,0xDB,0xF6,0xCB,0xB3,0x39,
+ 0x02,0x5B,0x78,0x62,0xFB,0x09,0xAE,0x09,0x6B,0xDD,0xD4,0x5D,
+ 0x97,0xBC,0xDC,0x7F,0xE6,0xD6,0xF1,0xCB,0xF5,0xEB,0xDA,0xA7,
+ 0x2E,0x5A,0x43,0x2B,0xE9,0x40,0xE2,0x85,0x00,0x1C,0xC0,0x0A,
+ 0x98,0x77,0xA9,0x31,0xDE,0x0B,0x75,0x4D,0x1E,0x1F,0x16,0x83,
+ 0xCA,0xDE,0xBD,0x21,0xFC,0xC1,0x82,0x37,0x36,0x33,0x0B,0x66,
+ 0x06,0x3C,0xF3,0xAF,0x21,0x57,0x57,0x80,0xF6,0x94,0x1B,0xA9,
+ 0xD4,0xF6,0x8F,0x18,0x62,0x0E,0xC4,0x22,0xF9,0x5B,0x62,0xCC,
+ 0x3F,0x19,0x95,0xCF,0x4B,0x00,0xA6,0x6C,0x0B,0xAF,0x9F,0xD5,
+ 0xFA,0x3D,0x6D,0xDA,0x30,0x83,0x07,0x91,0xAC,0x15,0xFF,0x8F,
+ 0x59,0x54,0xEA,0x25,0xBC,0x4E,0xEB,0x6A,0x54,0xDF,0x75,0x09,
+ 0x72,0x0F,0xEF,0x23,0x70,0xE0,0xA8,0x04,0xEA,0xFF,0x90,0x54,
+ 0xCD,0x84,0x18,0xC0,0x75,0x91,0x99,0x0F,0xA1,0x78,0x0C,0x07,
+ 0xB7,0xC5,0xDE,0x55,0x06,0x7B,0x95,0x68,0x2C,0x33,0x39,0xBC,
+ 0x2C,0xD0,0x6D,0xDD,0xFA,0xDC,0xB5,0x8F,0x82,0x39,0xF8,0x67,
+ 0x44,0xF1,0xD8,0xF7,0x78,0x11,0x9A,0x77,0x9B,0x53,0x47,0xD6,
+ 0x2B,0x5D,0x67,0xB8,0xB7,0xBC,0xC1,0xD7,0x79,0x62,0x15,0xC2,
+ 0xC5,0x83,0x97,0xA7,0xF8,0xB4,0x9C,0xF6,0x8F,0x9A,0xC7,0xDA,
+ 0x1B,0xBB,0x87,0x07,0xA7,0x71,0xAD,0xB2,0x8A,0x50,0xF8,0x26,
+ 0x12,0xB7,0x3E,0x0B,
+ };
+ static unsigned char dhg_2048[] = {
+ 0x02
+ };
+ DH *dh = DH_new();
+ BIGNUM *dhp_bn, *dhg_bn;
+
+ if (dh == NULL)
+ return NULL;
+ dhp_bn = BN_bin2bn(dhp_2048, sizeof (dhp_2048), NULL);
+ dhg_bn = BN_bin2bn(dhg_2048, sizeof (dhg_2048), NULL);
+ if (dhp_bn == NULL || dhg_bn == NULL
+ || !DH_set0_pqg(dh, dhp_bn, NULL, dhg_bn)) {
+ DH_free(dh);
+ BN_free(dhp_bn);
+ BN_free(dhg_bn);
+ return NULL;
+ }
+ return dh;
}
-
static const char*
-ssl_error_string[] =
+ssl_error_string[] =
{
"No error",
"Unable to get certificate",
@@ -148,9 +156,7 @@ static void check_ssl_init()
if (!ssl_algorithms_added)
{
ssl_algorithms_added= TRUE;
- SSL_library_init();
- OpenSSL_add_all_algorithms();
-
+ OPENSSL_init_ssl(0, NULL);
}
if (!ssl_error_strings_loaded)