[Openvpn-devel] OpenSSL: Fix compilation with deprecated APIs disabled on 1.1

Message ID 20180620044650.18041-1-rosenp@gmail.com
State Changes Requested
Headers show
Series [Openvpn-devel] OpenSSL: Fix compilation with deprecated APIs disabled on 1.1 | expand

Commit Message

Rosen Penev June 19, 2018, 6:46 p.m. UTC
Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
 src/openvpn/crypto_openssl.c     |  9 +++++++++
 src/openvpn/ssl_openssl.c        | 32 +++++++++++++++++++++++++++++++-
 src/openvpn/ssl_verify_openssl.c |  1 +
 3 files changed, 41 insertions(+), 1 deletion(-)

Comments

Gert Doering June 19, 2018, 7 p.m. UTC | #1
Hi,

On Tue, Jun 19, 2018 at 09:46:50PM -0700, Rosen Penev wrote:
> Signed-off-by: Rosen Penev <rosenp@gmail.com>
> ---
>  src/openvpn/crypto_openssl.c     |  9 +++++++++
>  src/openvpn/ssl_openssl.c        | 32 +++++++++++++++++++++++++++++++-
>  src/openvpn/ssl_verify_openssl.c |  1 +
>  3 files changed, 41 insertions(+), 1 deletion(-)
> 
> diff --git a/src/openvpn/crypto_openssl.c b/src/openvpn/crypto_openssl.c
> index 4fb2f6d6..816d8002 100644
> --- a/src/openvpn/crypto_openssl.c
> +++ b/src/openvpn/crypto_openssl.c
> @@ -670,11 +670,16 @@ cipher_ctx_init(EVP_CIPHER_CTX *ctx, const uint8_t *key, int key_len,
>  {
>      ASSERT(NULL != kt && NULL != ctx);
>  
> +#if OPENSSL_VERSION_NUMBER < 0x10100000L
>      EVP_CIPHER_CTX_init(ctx);
> +#else
> +    EVP_CIPHER_CTX_new();
> +#endif

Thanks for the patch, but this is not the way we want our source to
look like.  As in: these extra #if will make maintaining the code
harder and more error-prone.


A patch along the lines of the existing openssl 1.1 / 1.0 compat layer
(the .c files call the 1.1 API and if that API is not available, 
openssl_compat.h provides a substitute function) would be something
we might look more closely into.

gert
Emmanuel Deloget June 20, 2018, 2:40 a.m. UTC | #2
Hello Rosen,

On Wed, Jun 20, 2018 at 7:00 AM Gert Doering <gert@greenie.muc.de> wrote:
>
> Hi,
>
> On Tue, Jun 19, 2018 at 09:46:50PM -0700, Rosen Penev wrote:
> > Signed-off-by: Rosen Penev <rosenp@gmail.com>
> > ---
> >  src/openvpn/crypto_openssl.c     |  9 +++++++++
> >  src/openvpn/ssl_openssl.c        | 32 +++++++++++++++++++++++++++++++-
> >  src/openvpn/ssl_verify_openssl.c |  1 +
> >  3 files changed, 41 insertions(+), 1 deletion(-)

Can you give a better explanation of the issue ? (I'm sorry, I try to
follow the discussions on the ML, but I'm kind of slow (and busy,
which does not help)).

Best regards,

-- Emmanuel Deloget

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
Gert Doering June 20, 2018, 2:52 a.m. UTC | #3
Hi,

On Wed, Jun 20, 2018 at 02:40:43PM +0200, Emmanuel Deloget wrote:
> Can you give a better explanation of the issue ? (I'm sorry, I try to
> follow the discussions on the ML, but I'm kind of slow (and busy,
> which does not help)).

If I understood the discussion right, you can compile OpenSSL 1.1
with flags that remove APIs that are considered "legacy, deprecated" - 
and if you do so, OpenVPN won't build anymore.

I have not looked into details - I saw "20 extra #ifdef" and decided
"this is not how we (well, Emmanuel ;-) ) do things".  And thanks again
for doing the 1.1 support in a way that results in clean code without
#ifdefs ;-)

gert
Arne Schwabe June 20, 2018, 2:59 a.m. UTC | #4
Am 20.06.18 um 14:40 schrieb Emmanuel Deloget:
> Hello Rosen,
> 
> On Wed, Jun 20, 2018 at 7:00 AM Gert Doering <gert@greenie.muc.de> wrote:
>>
>> Hi,
>>
>> On Tue, Jun 19, 2018 at 09:46:50PM -0700, Rosen Penev wrote:
>>> Signed-off-by: Rosen Penev <rosenp@gmail.com>
>>> ---
>>>  src/openvpn/crypto_openssl.c     |  9 +++++++++
>>>  src/openvpn/ssl_openssl.c        | 32 +++++++++++++++++++++++++++++++-
>>>  src/openvpn/ssl_verify_openssl.c |  1 +
>>>  3 files changed, 41 insertions(+), 1 deletion(-)
> 
> Can you give a better explanation of the issue ? (I'm sorry, I try to
> follow the discussions on the ML, but I'm kind of slow (and busy,
> which does not help)).

For function that are different in OpenSSL 1.0 and 1.1 we put them into
the compat_openssl.h instead of adding ifdefs in the code.

Most time we implement the new function name with the old API to have
only the new API in OpenVPN itself. E.g. SSLeay_version would be
implemented via OpenSSL_version


And while I am here:

>  #if OPENSSL_VERSION_NUMBER >= 0x10002000L
>          /* OpenSSL 1.0.2 and newer can automatically handle ECDH parameter
>           * loading */
> +#if OPENSSL_VERSION_NUMBER < 0x10100000L
>          SSL_CTX_set_ecdh_auto(ctx->ctx, 1);
> +#endif
>          return;
>  #else

That ifdef removal needs a bit more explaination (e.g. that function
being a dummy with compat layer).

Arne

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
Rosen Penev June 21, 2018, 3:42 p.m. UTC | #5
On Tue, Jun 19, 2018 at 10:00 PM Gert Doering <gert@greenie.muc.de> wrote:
>
> Hi,
>
> On Tue, Jun 19, 2018 at 09:46:50PM -0700, Rosen Penev wrote:
> > Signed-off-by: Rosen Penev <rosenp@gmail.com>
> > ---
> >  src/openvpn/crypto_openssl.c     |  9 +++++++++
> >  src/openvpn/ssl_openssl.c        | 32 +++++++++++++++++++++++++++++++-
> >  src/openvpn/ssl_verify_openssl.c |  1 +
> >  3 files changed, 41 insertions(+), 1 deletion(-)
> >
> > diff --git a/src/openvpn/crypto_openssl.c b/src/openvpn/crypto_openssl.c
> > index 4fb2f6d6..816d8002 100644
> > --- a/src/openvpn/crypto_openssl.c
> > +++ b/src/openvpn/crypto_openssl.c
> > @@ -670,11 +670,16 @@ cipher_ctx_init(EVP_CIPHER_CTX *ctx, const uint8_t *key, int key_len,
> >  {
> >      ASSERT(NULL != kt && NULL != ctx);
> >
> > +#if OPENSSL_VERSION_NUMBER < 0x10100000L
> >      EVP_CIPHER_CTX_init(ctx);
> > +#else
> > +    EVP_CIPHER_CTX_new();
> > +#endif
>
> Thanks for the patch, but this is not the way we want our source to
> look like.  As in: these extra #if will make maintaining the code
> harder and more error-prone.
>
>
> A patch along the lines of the existing openssl 1.1 / 1.0 compat layer
> (the .c files call the 1.1 API and if that API is not available,
> openssl_compat.h provides a substitute function) would be something
> we might look more closely into.
I ran this on a client. Turns out there are more problems than this. I
will submit a partial fix in the meantime.
>
> gert
>
> --
> "If was one thing all people took for granted, was conviction that if you
>  feed honest figures into a computer, honest figures come out. Never doubted
>  it myself till I met a computer with a sense of humor."
>                              Robert A. Heinlein, The Moon is a Harsh Mistress
>
> Gert Doering - Munich, Germany                             gert@greenie.muc.de

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot

Patch

diff --git a/src/openvpn/crypto_openssl.c b/src/openvpn/crypto_openssl.c
index 4fb2f6d6..816d8002 100644
--- a/src/openvpn/crypto_openssl.c
+++ b/src/openvpn/crypto_openssl.c
@@ -670,11 +670,16 @@  cipher_ctx_init(EVP_CIPHER_CTX *ctx, const uint8_t *key, int key_len,
 {
     ASSERT(NULL != kt && NULL != ctx);
 
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
     EVP_CIPHER_CTX_init(ctx);
+#else
+    EVP_CIPHER_CTX_new();
+#endif
     if (!EVP_CipherInit(ctx, kt, NULL, NULL, enc))
     {
         crypto_msg(M_FATAL, "EVP cipher init #1");
     }
+
 #ifdef HAVE_EVP_CIPHER_CTX_SET_KEY_LENGTH
     if (!EVP_CIPHER_CTX_set_key_length(ctx, key_len))
     {
@@ -693,7 +698,11 @@  cipher_ctx_init(EVP_CIPHER_CTX *ctx, const uint8_t *key, int key_len,
 void
 cipher_ctx_cleanup(EVP_CIPHER_CTX *ctx)
 {
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
     EVP_CIPHER_CTX_cleanup(ctx);
+#else
+    EVP_CIPHER_CTX_free(ctx);
+#endif
 }
 
 int
diff --git a/src/openvpn/ssl_openssl.c b/src/openvpn/ssl_openssl.c
index 527a600a..92ed4926 100644
--- a/src/openvpn/ssl_openssl.c
+++ b/src/openvpn/ssl_openssl.c
@@ -56,6 +56,15 @@ 
 #include <openssl/pkcs12.h>
 #include <openssl/x509.h>
 #include <openssl/crypto.h>
+#ifndef OPENSSL_NO_DH
+#include <openssl/dh.h>
+#endif
+#ifndef OPENSSL_NO_DSA
+#include <openssl/dsa.h>
+#endif
+#ifndef OPENSSL_NO_RSA
+#include <openssl/rsa.h>
+#endif
 #ifndef OPENSSL_NO_EC
 #include <openssl/ec.h>
 #endif
@@ -71,11 +80,19 @@  int mydata_index; /* GLOBAL */
 void
 tls_init_lib(void)
 {
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
     SSL_library_init();
+    OpenSSL_add_all_algorithms();
 #ifndef ENABLE_SMALL
     SSL_load_error_strings();
 #endif
-    OpenSSL_add_all_algorithms();
+#else
+#ifndef ENABLE_SMALL
+    OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
+#else
+    OPENSSL_init_ssl(OPENSSL_INIT_NO_LOAD_SSL_STRINGS, NULL);
+#endif
+#endif
 
     mydata_index = SSL_get_ex_new_index(0, "struct session *", NULL, NULL, NULL);
     ASSERT(mydata_index >= 0);
@@ -84,10 +101,12 @@  tls_init_lib(void)
 void
 tls_free_lib(void)
 {
+#if OPENSSL_VERSION_NUMBER < 0x10100000L //this is no-op in future versions
     EVP_cleanup();
 #ifndef ENABLE_SMALL
     ERR_free_strings();
 #endif
+#endif
 }
 
 void
@@ -473,6 +492,11 @@  tls_ctx_check_cert_time(const struct tls_root_ctx *ctx)
         goto cleanup; /* Nothing to check if there is no certificate */
     }
 
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+#define X509_get_notBefore    X509_get0_notBefore
+#define X509_get_notAfter     X509_get0_notAfter
+#endif
+
     ret = X509_cmp_time(X509_get_notBefore(cert), NULL);
     if (ret == 0)
     {
@@ -567,7 +591,9 @@  tls_ctx_load_ecdh_params(struct tls_root_ctx *ctx, const char *curve_name
 #if OPENSSL_VERSION_NUMBER >= 0x10002000L
         /* OpenSSL 1.0.2 and newer can automatically handle ECDH parameter
          * loading */
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
         SSL_CTX_set_ecdh_auto(ctx->ctx, 1);
+#endif
         return;
 #else
         /* For older OpenSSL we have to extract the curve from key on our own */
@@ -2037,7 +2063,11 @@  get_highest_preference_tls_cipher(char *buf, int size)
 const char *
 get_ssl_library_version(void)
 {
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
     return SSLeay_version(SSLEAY_VERSION);
+#else
+    return OpenSSL_version(OPENSSL_VERSION);
+#endif
 }
 
 #endif /* defined(ENABLE_CRYPTO_OPENSSL) */
diff --git a/src/openvpn/ssl_verify_openssl.c b/src/openvpn/ssl_verify_openssl.c
index 9b984751..82460ae7 100644
--- a/src/openvpn/ssl_verify_openssl.c
+++ b/src/openvpn/ssl_verify_openssl.c
@@ -46,6 +46,7 @@ 
 
 #include <openssl/x509v3.h>
 #include <openssl/err.h>
+#include <openssl/bn.h>
 
 int
 verify_callback(int preverify_ok, X509_STORE_CTX *ctx)