maria-developers team mailing list archive
-
maria-developers team
-
Mailing list archive
-
Message #10254
Re: Review for MDEV-10332
Hi, Georg!
First, I've looked a bit at EVP_CIPHER_CTX_new/etc.
With the CRYPTO_set_mem_functions() one can overwrite malloc/realloc/free
functions that OpenSSL is using. We absolutely should do it.
At the very least, OpenSSL should use my_malloc/my_realloc/my_free.
But a more interesting approach would be to allocate a buffer on the
stack and let our openssl m/r/f helpers take the memory from there.
And print a warning with a fallback to malloc if that buffer isn't
enough. This way openssl won't need mallocs is most cases.
Still, I'd suggest to do this in a separate commit. In your main
"OpenSSL 1.1 support" commit, just use CRYPTO_set_mem_functions to
put OpenSSL through my_malloc/my_realloc/my_free.
On Nov 15, Georg Richter wrote:
> From 6103b311c4c5740998d342afbba9ac70f8ec5731 Mon Sep 17 00:00:00 2001
> From: Georg Richter <georg@xxxxxxxxxxx>
> Date: Tue, 15 Nov 2016 18:39:54 +0100
> Subject: [PATCH] MDEV-10332: Added support for OpenSSL 1.1
>
> diff --git a/mysql-test/r/openssl_6975,tlsv10.result b/mysql-test/r/openssl_6975,tlsv10.result
> index a65167f..e216ec2 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 "DES-CBC3-SHA";
did you verify that after your changes all tests also work with older
openssl versions and with yassl?
> 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
> diff --git a/mysys_ssl/my_crypt.cc b/mysys_ssl/my_crypt.cc
> index 49bd9af..d72bc72 100644
> --- a/mysys_ssl/my_crypt.cc
> +++ b/mysys_ssl/my_crypt.cc
> @@ -36,9 +36,20 @@
> 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;
> +#if defined(HAVE_YASSL)
> + MyCTX() { ctx= new EVP_CIPHER_CTX; EVP_CIPHER_CTX_init(ctx); }
> + virtual ~MyCTX() { EVP_CIPHER_CTX_cleanup(ctx); delete ctx; ERR_remove_state(0); }
> +#else
> + MyCTX() {ctx= EVP_CIPHER_CTX_new(); EVP_CIPHER_CTX_init(ctx); }
> + virtual ~MyCTX() { EVP_CIPHER_CTX_free(ctx);
> +#if OPENSSL_VERSION_NUMBER < 0x10100000L
> + ERR_remove_state(0);
> +#else
> + ERR_clear_error();
> +#endif
> + }
> +#endif
No #ifdef's here, please. YaSSL-specific code from mysys_ssl/yassl.cc
makes yassl to look sufficiently like openssl, so that
mysys_ssl/my_crypt.cc wouldn't need any ifdefs. Please, keep it that
way.
And, certainly, don't put any #if's that check openssl version in the
code, keep them in the headers or in the beginning of the file (there
is, already #define ERR_remove_state(X) there)
> virtual int init(const EVP_CIPHER *cipher, int encrypt, const uchar *key,
> uint klen, const uchar *iv, uint ivlen)
> @@ -72,7 +83,10 @@ class MyCTX_nopad : public MyCTX
> {
> public:
> const uchar *key;
> + const uchar *src;
> int klen;
> + uchar oiv[90];
90 bytes for an IV?
> + uint extra_bytes;
>
> MyCTX_nopad() : MyCTX() { }
> ~MyCTX_nopad() { }
> @@ -285,7 +310,11 @@ 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.
> */
> +#if OPENSSL_VERSION_NUMBER < 0x10100000L
> RAND_METHOD *rand = RAND_SSLeay();
> +#else
> + RAND_METHOD *rand = RAND_OpenSSL();
> +#endif
no #if's in the code, please
> 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 7139ea9..4885033 100644
> --- a/mysys_ssl/my_md5.cc
> +++ b/mysys_ssl/my_md5.cc
> @@ -58,10 +57,11 @@ static void md5_result(MD5_CONTEXT *context, uchar digest[MD5_HASH_SIZE])
>
> #elif defined(HAVE_OPENSSL)
> #include <openssl/evp.h>
> -typedef EVP_MD_CTX MD5_CONTEXT;
> +typedef void MD5_CONTEXT;
>
> -static void md5_init(MD5_CONTEXT *context)
> +static void md5_init(MD5_CONTEXT *ctx)
> {
> + EVP_MD_CTX *context= (EVP_MD_CTX *)ctx;
> EVP_MD_CTX_init(context);
> #ifdef EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
> /* Ok to ignore FIPS: MD5 is not used for crypto here */
> @@ -123,21 +143,43 @@ void my_md5_multi(uchar *digest, ...)
> {
> va_list args;
> va_start(args, digest);
> -
> - MD5_CONTEXT md5_context;
> +#ifdef HAVE_YASSL
> + MD5_CONTEXT *md5_context= new MD5_CONTEXT;
> +#else
> +#if OPENSSL_VERSION_NUMBER < 0x10100000L
> + EVP_MD_CTX *md5_context= (EVP_MD_CTX *)alloca(sizeof(EVP_MD_CTX));
> +#else
> + EVP_MD_CTX *md5_context= EVP_MD_CTX_new();
> +#endif
> +#endif
> const uchar *str;
>
> - md5_init_fast(&md5_context);
> + md5_init_fast(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, str, va_arg(args, size_t));
>
> - md5_result(&md5_context, digest);
> + md5_result(md5_context, digest);
> va_end(args);
> +#if defined(HAVE_YASSL)
> + delete md5_context;
> +#else
> +#if OPENSSL_VERSION_NUMBER >= 0x10100000L
> + EVP_MD_CTX_free(md5_context);
> +#endif
> +#endif
> }
>
> size_t my_md5_context_size()
> {
> +#if defined(HAVE_YASSL)
> return sizeof(MD5_CONTEXT);
> +#elif OPENSSL_VERSION_NUMBER < 0x10100000L
> + return sizeof(EVP_MD_CTX);
> +#else
> + /* Since OpenSSL 1.1 we can't determine the length of EVP_MD_CTX anymore,
> + so we need to return a number (48 bytes + 16 bytes reserved) */
> + return 64;
How can you be sure that it's enough?
I'd just return sizeof(void*) and in
md5_init stored a return value of EVP_MD_CTX_new() there.
Until we do that optimization that I mentioned in the beginning of the
email.
And get rid of #if's please.
> +#endif
> }
Regards,
Sergei
Chief Architect MariaDB
and security@xxxxxxxxxxx