summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--extra/yassl/src/handshake.cpp10
-rw-r--r--include/my_crypt.h15
-rw-r--r--include/violite.h9
-rw-r--r--mysql-test/include/require_openssl_client.inc5
-rwxr-xr-xmysql-test/mysql-test-run.pl5
-rw-r--r--mysql-test/r/openssl_1.result2
-rw-r--r--mysql-test/r/openssl_6975,tlsv10.result10
-rw-r--r--mysql-test/r/openssl_6975,tlsv12.result6
-rw-r--r--mysql-test/t/openssl_1.test2
-rw-r--r--mysql-test/t/openssl_6975.test19
-rw-r--r--mysql-test/t/ssl_7937.test2
-rw-r--r--mysql-test/t/ssl_8k_key.test1
-rw-r--r--mysys_ssl/my_crypt.cc115
-rw-r--r--mysys_ssl/my_md5.cc39
-rw-r--r--mysys_ssl/yassl.cc15
-rw-r--r--sql-common/client.c6
-rw-r--r--sql/mysqld.cc14
-rw-r--r--sql/slave.cc13
-rw-r--r--vio/viosslfactories.c54
19 files changed, 254 insertions, 88 deletions
diff --git a/extra/yassl/src/handshake.cpp b/extra/yassl/src/handshake.cpp
index 407e4092ccc..6e181a997bd 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/my_crypt.h b/include/my_crypt.h
index 719e349bfb9..e7dd9d80100 100644
--- a/include/my_crypt.h
+++ b/include/my_crypt.h
@@ -21,4 +21,19 @@
#include <my_config.h> /* HAVE_EncryptAes128{Ctr,Gcm} */
#include <mysql/service_my_crypt.h>
+/* OpenSSL version specific definitions */
+#if !defined(HAVE_YASSL) && defined(OPENSSL_VERSION_NUMBER)
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+#define ERR_remove_state(X)
+#else
+#define EVP_CIPHER_CTX_reset(X) EVP_CIPHER_CTX_cleanup(X)
+#define RAND_OpenSSL() RAND_SSLeay();
+#if defined(HAVE_ERR_remove_thread_state)
+#define ERR_remove_state(X) ERR_remove_thread_state(NULL)
+#endif
+#endif
+#elif defined(HAVE_YASSL)
+#define EVP_CIPHER_CTX_reset(X) EVP_CIPHER_CTX_cleanup(X)
+#endif /* !defined(HAVE_YASSL) */
+
#endif /* MY_CRYPT_INCLUDED */
diff --git a/include/violite.h b/include/violite.h
index 6047c7c8fd4..78ca45da6f1 100644
--- a/include/violite.h
+++ b/include/violite.h
@@ -146,14 +146,15 @@ typedef my_socket YASSL_SOCKET_T;
#include <openssl/ssl.h>
#include <openssl/err.h>
-#ifdef HAVE_ERR_remove_thread_state
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+#define ERR_remove_state(X)
+#elif defined(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 00000000000..9b19960041b
--- /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 088dd3aae2c..dbac60d6248 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -2279,6 +2279,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_1.result b/mysql-test/r/openssl_1.result
index f28c399ce74..5495f8ffd34 100644
--- a/mysql-test/r/openssl_1.result
+++ b/mysql-test/r/openssl_1.result
@@ -209,7 +209,7 @@ DROP TABLE t1;
Variable_name Value
Ssl_cipher AES256-SHA
Variable_name Value
-Ssl_cipher DES-CBC3-SHA
+Ssl_cipher AES128-SHA
select 'is still running; no cipher request crashed the server' as result from dual;
result
is still running; no cipher request crashed the server
diff --git a/mysql-test/r/openssl_6975,tlsv10.result b/mysql-test/r/openssl_6975,tlsv10.result
index a65167ff427..b76a91bd134 100644
--- a/mysql-test/r/openssl_6975,tlsv10.result
+++ b/mysql-test/r/openssl_6975,tlsv10.result
@@ -1,11 +1,11 @@
create user ssl_sslv3@localhost;
-grant select on test.* to ssl_sslv3@localhost require cipher "RC4-SHA";
+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: sslv3 alert handshake failure
ERROR 2026 (HY000): SSL connection error: sslv3 alert handshake failure
-TLS1.2 ciphers: user requires SSLv3 cipher RC4-SHA
+TLS1.2 ciphers: user requires SSLv3 cipher AES128-SHA
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
@@ -13,12 +13,12 @@ ERROR 2026 (HY000): SSL connection error: sslv3 alert handshake failure
ERROR 2026 (HY000): SSL connection error: sslv3 alert handshake failure
SSLv3 ciphers: user is ok with any cipher
Variable_name Value
-Ssl_cipher RC4-SHA
+Ssl_cipher AES256-SHA
Variable_name Value
Ssl_cipher DHE-RSA-AES256-SHA
-SSLv3 ciphers: user requires SSLv3 cipher RC4-SHA
+SSLv3 ciphers: user requires SSLv3 cipher AES128-SHA
Variable_name Value
-Ssl_cipher RC4-SHA
+Ssl_cipher AES128-SHA
ERROR 1045 (28000): Access denied for user 'ssl_sslv3'@'localhost' (using password: NO)
SSLv3 ciphers: user requires TLSv1.2 cipher AES128-SHA256
ERROR 1045 (28000): Access denied for user 'ssl_tls12'@'localhost' (using password: NO)
diff --git a/mysql-test/r/openssl_6975,tlsv12.result b/mysql-test/r/openssl_6975,tlsv12.result
index 8758daa7011..c16e503c339 100644
--- a/mysql-test/r/openssl_6975,tlsv12.result
+++ b/mysql-test/r/openssl_6975,tlsv12.result
@@ -1,5 +1,5 @@
create user ssl_sslv3@localhost;
-grant select on test.* to ssl_sslv3@localhost require cipher "RC4-SHA";
+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
@@ -7,7 +7,7 @@ Variable_name Value
Ssl_cipher AES128-SHA256
Variable_name Value
Ssl_cipher DHE-RSA-AES256-GCM-SHA384
-TLS1.2 ciphers: user requires SSLv3 cipher RC4-SHA
+TLS1.2 ciphers: user requires SSLv3 cipher AES128-SHA
ERROR 1045 (28000): Access denied for user 'ssl_sslv3'@'localhost' (using password: NO)
ERROR 1045 (28000): Access denied for user 'ssl_sslv3'@'localhost' (using password: NO)
TLS1.2 ciphers: user requires TLSv1.2 cipher AES128-SHA256
@@ -17,7 +17,7 @@ ERROR 1045 (28000): Access denied for user 'ssl_tls12'@'localhost' (using passwo
SSLv3 ciphers: user is ok with any cipher
ERROR 2026 (HY000): SSL connection error: sslv3 alert handshake failure
ERROR 2026 (HY000): SSL connection error: sslv3 alert handshake failure
-SSLv3 ciphers: user requires SSLv3 cipher RC4-SHA
+SSLv3 ciphers: user requires SSLv3 cipher AES128-SHA
ERROR 2026 (HY000): SSL connection error: sslv3 alert handshake failure
ERROR 2026 (HY000): SSL connection error: sslv3 alert handshake failure
SSLv3 ciphers: user requires TLSv1.2 cipher AES128-SHA256
diff --git a/mysql-test/t/openssl_1.test b/mysql-test/t/openssl_1.test
index 8e2d9133359..35bb7aca085 100644
--- a/mysql-test/t/openssl_1.test
+++ b/mysql-test/t/openssl_1.test
@@ -225,7 +225,7 @@ DROP TABLE t1;
# Common ciphers to openssl and yassl
--exec $MYSQL --host=localhost -e "SHOW STATUS LIKE 'Ssl_cipher';" --ssl-cipher=AES256-SHA
---exec $MYSQL --host=localhost -e "SHOW STATUS LIKE 'Ssl_cipher';" --ssl-cipher=DES-CBC3-SHA
+--exec $MYSQL --host=localhost -e "SHOW STATUS LIKE 'Ssl_cipher';" --ssl-cipher=AES128-SHA
--disable_query_log
--disable_result_log
diff --git a/mysql-test/t/openssl_6975.test b/mysql-test/t/openssl_6975.test
index 6e8e03a0a89..6cf5d82cf54 100644
--- a/mysql-test/t/openssl_6975.test
+++ b/mysql-test/t/openssl_6975.test
@@ -4,11 +4,13 @@
# 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.
create user ssl_sslv3@localhost;
-grant select on test.* to ssl_sslv3@localhost require cipher "RC4-SHA";
+# grant select on test.* to ssl_sslv3@localhost require cipher "AES128-SHA";
+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";
@@ -18,8 +20,9 @@ disable_abort_on_error;
echo TLS1.2 ciphers: user is ok with any cipher;
exec $mysql --ssl-cipher=AES128-SHA256;
--replace_result DHE-RSA-CHACHA20-POLY1305 DHE-RSA-AES256-GCM-SHA384
-exec $mysql --ssl-cipher=TLSv1.2;
-echo TLS1.2 ciphers: user requires SSLv3 cipher RC4-SHA;
+--replace_result ECDHE-RSA-AES256-GCM-SHA384 DHE-RSA-AES256-GCM-SHA384
+exec $mysql --ssl-cipher=TLSv1.2
+echo TLS1.2 ciphers: user requires SSLv3 cipher AES128-SHA;
exec $mysql --user ssl_sslv3 --ssl-cipher=AES128-SHA256;
exec $mysql --user ssl_sslv3 --ssl-cipher=TLSv1.2;
echo TLS1.2 ciphers: user requires TLSv1.2 cipher AES128-SHA256;
@@ -27,13 +30,13 @@ exec $mysql --user ssl_tls12 --ssl-cipher=AES128-SHA256;
exec $mysql --user ssl_tls12 --ssl-cipher=TLSv1.2;
echo SSLv3 ciphers: user is ok with any cipher;
-exec $mysql --ssl-cipher=RC4-SHA;
-exec $mysql --ssl-cipher=SSLv3;
-echo SSLv3 ciphers: user requires SSLv3 cipher RC4-SHA;
-exec $mysql --user ssl_sslv3 --ssl-cipher=RC4-SHA;
+exec $mysql --ssl-cipher=AES256-SHA;
+exec $mysql --ssl-cipher=DHE-RSA-AES256-SHA
+echo SSLv3 ciphers: user requires SSLv3 cipher AES128-SHA;
+exec $mysql --user ssl_sslv3 --ssl-cipher=AES128-SHA;
exec $mysql --user ssl_sslv3 --ssl-cipher=SSLv3;
echo SSLv3 ciphers: user requires TLSv1.2 cipher AES128-SHA256;
-exec $mysql --user ssl_tls12 --ssl-cipher=RC4-SHA;
+exec $mysql --user ssl_tls12 --ssl-cipher=AES128-SHA;
exec $mysql --user ssl_tls12 --ssl-cipher=SSLv3;
drop user ssl_sslv3@localhost;
diff --git a/mysql-test/t/ssl_7937.test b/mysql-test/t/ssl_7937.test
index 8e9d1901907..aa8cd225d7b 100644
--- a/mysql-test/t/ssl_7937.test
+++ b/mysql-test/t/ssl_7937.test
@@ -26,7 +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"
+ --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 23267a3c611..299bfaf494d 100644
--- a/mysql-test/t/ssl_8k_key.test
+++ b/mysql-test/t/ssl_8k_key.test
@@ -1,4 +1,5 @@
# This test should work in embedded server after we fix mysqltest
+-- source include/require_openssl_client.inc
-- source include/not_embedded.inc
-- source include/have_ssl_communication.inc
diff --git a/mysys_ssl/my_crypt.cc b/mysys_ssl/my_crypt.cc
index 2ab38711d0f..9cacee4b450 100644
--- a/mysys_ssl/my_crypt.cc
+++ b/mysys_ssl/my_crypt.cc
@@ -17,7 +17,6 @@
#include <my_global.h>
#include <string.h>
-#include <my_crypt.h>
#ifdef HAVE_YASSL
#include "yassl.cc"
@@ -26,43 +25,51 @@
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <openssl/err.h>
+#include <openssl/rand.h>
-#ifdef HAVE_ERR_remove_thread_state
-#define ERR_remove_state(X) ERR_remove_thread_state(NULL)
#endif
+#include <my_crypt.h>
-#endif
+#define MY_CIPHER_CTX_SIZE 384
class MyCTX
{
public:
- EVP_CIPHER_CTX ctx;
- MyCTX() { EVP_CIPHER_CTX_init(&ctx); }
- virtual ~MyCTX() { EVP_CIPHER_CTX_cleanup(&ctx); ERR_remove_state(0); }
+ EVP_CIPHER_CTX *ctx;
+ const uchar *key;
+ unsigned int klen;
+ MyCTX() {
+ ctx= EVP_CIPHER_CTX_new();
+ }
+ virtual ~MyCTX() {
+ EVP_CIPHER_CTX_free(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;
}
@@ -71,11 +78,9 @@ public:
class MyCTX_nopad : public MyCTX
{
public:
- const uchar *key;
- int klen;
-
MyCTX_nopad() : MyCTX() { }
~MyCTX_nopad() { }
+ unsigned int buf_len;
int init(const EVP_CIPHER *cipher, int encrypt, const uchar *key, uint klen,
const uchar *iv, uint ivlen)
@@ -83,16 +88,39 @@ public:
compile_time_assert(MY_AES_CTX_SIZE >= sizeof(MyCTX_nopad));
this->key= key;
this->klen= klen;
+ this->buf_len= 0;
+ /* FIX-ME:
+ For the sake of backward compatibility we do some strange hack here:
+ Since ECB doesn't need an IV (and therefore is considered kind of
+ insecure) we need to store the specified iv.
+ The last nonpadding block will be encrypted with an additional
+ expensive crypt_call in ctr mode instead
+ of encrypting the entire plain text in ctr-mode */
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+ const unsigned char *oiv= EVP_CIPHER_CTX_original_iv(ctx);
+#else
+ const unsigned char *oiv= ctx->oiv;
+#endif
+ memcpy((char *)oiv, iv, ivlen);
+
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 % MY_AES_BLOCK_SIZE;
+ return MyCTX::update(src, slen, dst, dlen);
+ }
+
int finish(uchar *dst, uint *dlen)
{
- if (ctx.buf_len)
+ if (buf_len)
{
+ const uchar *org_iv;
+ unsigned char *buf;
/*
Not much we can do, block ciphers cannot encrypt data that aren't
a multiple of the block length. At least not without padding.
@@ -101,14 +129,22 @@ public:
uchar mask[MY_AES_BLOCK_SIZE];
uint mlen;
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+ org_iv= EVP_CIPHER_CTX_original_iv(ctx);
+ buf= EVP_CIPHER_CTX_buf_noconst(ctx);
+#else
+ org_iv= ctx->oiv;
+ buf= ctx->buf;
+#endif
+
my_aes_crypt(MY_AES_ECB, ENCRYPTION_FLAG_ENCRYPT | ENCRYPTION_FLAG_NOPAD,
- ctx.oiv, sizeof(mask), mask, &mlen, key, klen, 0, 0);
+ org_iv, 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;
}
};
@@ -142,8 +178,9 @@ make_aes_dispatcher(gcm)
class MyCTX_gcm : public MyCTX
{
public:
- const uchar *aad;
+ const uchar *aad= NULL;
int aadlen;
+ my_bool encrypt;
MyCTX_gcm() : MyCTX() { }
~MyCTX_gcm() { }
@@ -152,9 +189,10 @@ public:
{
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;
+ this->encrypt= encrypt;
return res;
}
@@ -166,18 +204,18 @@ public:
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 (!this->encrypt)
{
/* encrypted string must contain authenticaton tag (see MDEV-11174) */
if (slen < MY_AES_BLOCK_SIZE)
return MY_AES_BAD_DATA;
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))
+ int unused= 0;
+ if (aadlen && !EVP_CipherUpdate(ctx, NULL, &unused, aad, aadlen))
return MY_AES_OPENSSL_ERROR;
aadlen= 0;
return MyCTX::update(src, slen, dst, dlen);
@@ -185,14 +223,14 @@ public:
int finish(uchar *dst, uint *dlen)
{
- int fin;
- if (!EVP_CipherFinal_ex(&ctx, dst, &fin))
+ int fin= 0;
+ if (!EVP_CipherFinal_ex(ctx, dst, &fin))
return MY_AES_BAD_DATA;
DBUG_ASSERT(fin == 0);
- if (ctx.encrypt)
+ if (this->encrypt)
{
- 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;
}
@@ -260,12 +298,20 @@ 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= 0;
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;
+ /* in case of failure clear error queue */
+#ifndef HAVE_YASSL
+ /* since we don't check the crypto error messages we need to
+ clear the error queue - otherwise subsequent crypto or tls/ssl
+ calls will fail */
+ if (!*dlen)
+ ERR_clear_error();
+#endif
return res1 ? res1 : res2;
}
@@ -304,7 +350,6 @@ int my_random_bytes(uchar* buf, int num)
return MY_AES_OK;
}
#else
-#include <openssl/rand.h>
int my_random_bytes(uchar *buf, int num)
{
@@ -314,7 +359,7 @@ int my_random_bytes(uchar *buf, int num)
instead of whatever random engine is currently set in OpenSSL. That way
we are guaranteed to have a non-blocking random.
*/
- RAND_METHOD *rand = RAND_SSLeay();
+ RAND_METHOD *rand = RAND_OpenSSL();
if (rand == NULL || rand->bytes(buf, num) != 1)
return MY_AES_OPENSSL_ERROR;
return MY_AES_OK;
diff --git a/mysys_ssl/my_md5.cc b/mysys_ssl/my_md5.cc
index 7139ea9b6ff..02c01dd7148 100644
--- a/mysys_ssl/my_md5.cc
+++ b/mysys_ssl/my_md5.cc
@@ -27,6 +27,8 @@
#include <my_md5.h>
#include <stdarg.h>
+#define MA_HASH_CTX_SIZE 512
+
#if defined(HAVE_YASSL)
#include "md5.hpp"
@@ -57,11 +59,18 @@ static void md5_result(MD5_CONTEXT *context, uchar digest[MD5_HASH_SIZE])
}
#elif defined(HAVE_OPENSSL)
+
+
#include <openssl/evp.h>
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+#define EVP_MD_CTX_reset(X) EVP_MD_CTX_cleanup(X)
+#endif
typedef EVP_MD_CTX MD5_CONTEXT;
static void md5_init(MD5_CONTEXT *context)
{
+ memset(context, 0, my_md5_context_size());
EVP_MD_CTX_init(context);
#ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
/* Ok to ignore FIPS: MD5 is not used for crypto here */
@@ -83,7 +92,7 @@ static void md5_input(MD5_CONTEXT *context, const uchar *buf, unsigned len)
static void md5_result(MD5_CONTEXT *context, uchar digest[MD5_HASH_SIZE])
{
EVP_DigestFinal_ex(context, digest, NULL);
- EVP_MD_CTX_cleanup(context);
+ EVP_MD_CTX_reset(context);
}
#endif /* HAVE_YASSL */
@@ -99,11 +108,14 @@ static void md5_result(MD5_CONTEXT *context, uchar digest[MD5_HASH_SIZE])
*/
void my_md5(uchar *digest, const char *buf, size_t len)
{
+#ifdef HAVE_YASSL
MD5_CONTEXT md5_context;
-
- md5_init_fast(&md5_context);
- md5_input(&md5_context, (const uchar *)buf, len);
- md5_result(&md5_context, digest);
+#else
+ unsigned char md5_context[MA_HASH_CTX_SIZE];
+#endif
+ md5_init_fast((MD5_CONTEXT *)&md5_context);
+ md5_input((MD5_CONTEXT *)&md5_context, (const uchar *)buf, len);
+ md5_result((MD5_CONTEXT *)&md5_context, digest);
}
@@ -122,22 +134,25 @@ void my_md5(uchar *digest, const char *buf, size_t len)
void my_md5_multi(uchar *digest, ...)
{
va_list args;
- va_start(args, digest);
-
- MD5_CONTEXT md5_context;
const uchar *str;
+#ifdef HAVE_YASSL
+ MD5_CONTEXT md5_context;
+#else
+ unsigned char md5_context[MA_HASH_CTX_SIZE];
+#endif
+ va_start(args, digest);
- md5_init_fast(&md5_context);
+ md5_init_fast((MD5_CONTEXT *)&md5_context);
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((MD5_CONTEXT *)&md5_context, str, va_arg(args, size_t));
- md5_result(&md5_context, digest);
+ md5_result((MD5_CONTEXT *)&md5_context, digest);
va_end(args);
}
size_t my_md5_context_size()
{
- return sizeof(MD5_CONTEXT);
+ return MA_HASH_CTX_SIZE;
}
void my_md5_init(void *context)
diff --git a/mysys_ssl/yassl.cc b/mysys_ssl/yassl.cc
index 5146c9a9abc..86acd315861 100644
--- a/mysys_ssl/yassl.cc
+++ b/mysys_ssl/yassl.cc
@@ -24,6 +24,7 @@
#include <openssl/ssl.h>
#include "aes.hpp"
+#include <my_sys.h>
using yaSSL::yaERR_remove_state;
@@ -75,12 +76,26 @@ static void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *ctx)
ctx->final_used= ctx->buf_len= ctx->flags= 0;
}
+static EVP_CIPHER_CTX *EVP_CIPHER_CTX_new()
+{
+ EVP_CIPHER_CTX *ctx= (EVP_CIPHER_CTX *)my_malloc(sizeof(EVP_CIPHER_CTX), MYF(0));
+ if (ctx)
+ EVP_CIPHER_CTX_init(ctx);
+ return ctx;
+}
+
static int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *ctx)
{
TAO(ctx)->~AES();
return 1;
}
+static void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx)
+{
+ EVP_CIPHER_CTX_cleanup(ctx);
+ my_free(ctx);
+}
+
static int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad)
{
if (pad)
diff --git a/sql-common/client.c b/sql-common/client.c
index 76dca42e14c..2aba1f99f33 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -104,6 +104,10 @@ my_bool net_flush(NET *net);
#define CONNECT_TIMEOUT 0
#endif
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) || defined(HAVE_YASSL)
+#define ASN1_STRING_get0_data(X) ASN1_STRING_data(X)
+#endif
+
#include "client_settings.h"
#include <sql_common.h>
#include <mysql/client_plugin.h>
@@ -1843,7 +1847,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 783beb22d5e..c6be6bfba4c 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -111,6 +111,7 @@
#endif
#include <my_systemd.h>
+#include <my_crypt.h>
#define mysqld_charset &my_charset_latin1
@@ -120,6 +121,7 @@
#define HAVE_CLOSE_SERVER_SOCK 1
#endif
+
extern "C" { // Because of SCO 3.2V4.2
#include <sys/stat.h>
#ifndef __GNU_LIBRARY__
@@ -1501,6 +1503,8 @@ scheduler_functions *thread_scheduler= &thread_scheduler_struct,
#ifdef HAVE_OPENSSL
#include <openssl/crypto.h>
#ifndef HAVE_YASSL
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
typedef struct CRYPTO_dynlock_value
{
mysql_rwlock_t lock;
@@ -1512,6 +1516,7 @@ 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
char *des_key_file;
#ifndef EMBEDDED_LIBRARY
struct st_VioSSLFd *ssl_acceptor_fd;
@@ -2331,9 +2336,11 @@ static void clean_up_mutexes()
#ifdef HAVE_OPENSSL
mysql_mutex_destroy(&LOCK_des_key_file);
#ifndef HAVE_YASSL
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
for (int i= 0; i < CRYPTO_num_locks(); ++i)
mysql_rwlock_destroy(&openssl_stdlocks[i].lock);
OPENSSL_free(openssl_stdlocks);
+#endif
#endif /* HAVE_YASSL */
#endif /* HAVE_OPENSSL */
#ifdef HAVE_REPLICATION
@@ -4695,6 +4702,7 @@ static int init_thread_environment()
mysql_mutex_init(key_LOCK_des_key_file,
&LOCK_des_key_file, MY_MUTEX_INIT_FAST);
#ifndef HAVE_YASSL
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
openssl_stdlocks= (openssl_lock_t*) OPENSSL_malloc(CRYPTO_num_locks() *
sizeof(openssl_lock_t));
for (int i= 0; i < CRYPTO_num_locks(); ++i)
@@ -4705,6 +4713,7 @@ static int init_thread_environment()
CRYPTO_set_locking_callback(openssl_lock_function);
#endif
#endif
+#endif
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);
@@ -4739,6 +4748,7 @@ static int init_thread_environment()
#if defined(HAVE_OPENSSL) && !defined(HAVE_YASSL)
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
static openssl_lock_t *openssl_dynlock_create(const char *file, int line)
{
openssl_lock_t *lock= new openssl_lock_t;
@@ -4798,6 +4808,7 @@ static void openssl_lock(int mode, openssl_lock_t *lock, const char *file,
abort();
}
}
+#endif
#endif /* HAVE_OPENSSL */
@@ -4827,8 +4838,9 @@ static void init_ssl()
while ((err= ERR_get_error()))
sql_print_warning("SSL error: %s", ERR_error_string(err, NULL));
}
- else
+ else {
ERR_remove_state(0);
+ }
}
else
{
diff --git a/sql/slave.cc b/sql/slave.cc
index 7e7144f08e7..611baf6c9bc 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -60,6 +60,11 @@
#include "debug_sync.h"
#include "rpl_parallel.h"
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+#define ERR_remove_state(X)
+#elif defined(HAVE_ERR_remove_thread_state)
+#define ERR_remove_state(X) ERR_remove_thread_state(NULL)
+#endif
#define FLAGSTR(V,F) ((V)&(F)?#F" ":"")
@@ -4673,7 +4678,11 @@ err_during_init:
DBUG_LEAVE; // Must match DBUG_ENTER()
my_thread_end();
#ifdef HAVE_OPENSSL
+#if OPENSSL_VERSION_NUMBER < 0x10000000L
ERR_remove_state(0);
+#elif OPENSSL_VERSION_NUMBER < 0x10100000L
+ ERR_remove_thread_state(0);
+#endif
#endif
pthread_exit(0);
return 0; // Avoid compiler warnings
@@ -5338,7 +5347,11 @@ err_during_init:
DBUG_LEAVE; // Must match DBUG_ENTER()
my_thread_end();
#ifdef HAVE_OPENSSL
+#if OPENSSL_VERSION_NUMBER < 0x10000000L
ERR_remove_state(0);
+#elif OPENSSL_VERSION_NUMBER < 0x10100000L
+ ERR_remove_thread_state(0);
+#endif
#endif
pthread_exit(0);
return 0; // Avoid compiler warnings
diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c
index 52b624d3376..497047cac72 100644
--- a/vio/viosslfactories.c
+++ b/vio/viosslfactories.c
@@ -17,17 +17,27 @@
#include "vio_priv.h"
#ifdef HAVE_OPENSSL
-#ifndef HAVE_YASSL
+#if defined(HAVE_YASSL) || defined(LIBRESSL_VERSION_NUMBER)
+#define OPENSSL_init_ssl(X,Y) SSL_library_init()
+#else
#include <openssl/dh.h>
#include <openssl/bn.h>
+
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+#define ERR_remove_state(X)
+#else
+#define OPENSSL_init_ssl(X,Y) SSL_library_init()
+#endif
+
#endif
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()
+
+/* {{{ get_dh_2048 */
+static DH *get_dh_2048()
{
static unsigned char dh2048_p[]={
0xA1,0xBB,0x7C,0x20,0xC5,0x5B,0xC0,0x7B,0x21,0x8B,0xD6,0xA8,
@@ -57,18 +67,32 @@ DH *get_dh2048()
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);
+ if ((dh=DH_new()) == NULL)
+ return(NULL);
+#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+ (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; }
+#else
+ {
+ BIGNUM *dhp_bn= BN_bin2bn(dh2048_p,sizeof(dh2048_p),NULL),
+ *dhg_bn= BN_bin2bn(dh2048_g,sizeof(dh2048_g),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;
+ }
+ }
+#endif
+ return dh;
}
-
static const char*
-ssl_error_string[] =
+ssl_error_string[] =
{
"No error",
"Unable to get certificate",
@@ -148,9 +172,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)
@@ -265,7 +287,7 @@ new_VioSSLFd(const char *key_file, const char *cert_file,
/* DH stuff */
if (!is_client_method)
{
- dh=get_dh2048();
+ dh=get_dh_2048();
if (!SSL_CTX_set_tmp_dh(ssl_fd->ssl_context, dh))
{
*error= SSL_INITERR_DH;