Add support for OpenSSL 1.1.x
cover Add support for OpenSSL 1.1.x
From: Emmanuel Deloget <[email protected]...>
The purpose of this RFC series is to make the latest master of OpenVPN (2.5-git) linkable with OpenSSL v1.1.x. It may not be complete (I may have missed something due to my work environment, but any missing pieces will be added next week) so be a bit cautious with this. The configuration I used (--without-systemd, --without-lzo) seems to work but I must confess I did not tested much.
As you may know, the important information about the API of OpenSSL 1.1 if that it no longer provide access to the content of its objects. The structure types are now opaque and various functions have been added to fetch information from these objects.
Once theses patches have been applied, it is possible to compile OpenSSL with the latest 1.0.1 and with the latest 1.1.0. I still have to check whether compilation with 1.0.0 and 0.9.8 works. I don't try to get the OpenSSL version -- I instead decided to check for the presence of individual functions in the library and chose to reimplement the missing ones. Then I changed caller code in order to use this new interface. The net result is that OpenVPN is now using the OpenSSL 1.1 API -- regardless of the real version of OpenSSL. This might make futur changes simpler at the cost of adding more functions in the openssl_compat.h file.
Las but not least, because of the way I worked I introduced some strange artefacts (I believe they are not really relevant but some of them are weird enough to need some explaination).
* I had to introduce a function of the 1.0 API in the 1.1 code. In the 1.0 API, HMAC_CTX is populated with HMAC_CTX_init() and cleaned with HMAC_CTX_cleanup(). In 1.1 these two functions are gone and replaced with HMAC_CTX_reset(). I decided to use _reset() to implement _cleanup() but since I then could not use it for _init() (that would break an OpenVPN linked with 1.0) I created a small wrapper in 1.1 mode. So, in 1.1, HMAC_CTX_init() calls _reset() -- and everybody is happy (well, maybe not everybody).
* HMAC_CTX, EVP_MD_CTX and a few other objects cannot be allocated using malloc() so I had to change the way these object are used and initialized. I introduces a few new functions in the crypto backend to handle this.
* x509_verify_ns_cert_type() checks had to be changed. OpenSSL 1.1 does not provide any solution to access both X509::ex_flags and X509::ex_nscert so the check could not be implemented this way. The only solution I found was to use X509_check_purpose() but I'm worried that the implemented test is now far more strict.
* weirdly enough, it's no longer possible to duplicate the n parameter of a RSA public key into another RSA public key. If you do so, you also need to duplicate the e parameter. The reason is that you cannot have (n && !e) or (!n && e) (see RSA_set0_key[1]). I deciced to go the same route in my implementation and thus I needed to change the code in tls_ctx_use_external_private_key().
Thanks for your comprehension,
[1] https://github.com/openssl/openssl/blob/master/crypto/rsa/rsa_lib.c#L191
-- Emmanuel Deloget
Emmanuel Deloget (15):
OpenSSL: don't use direct access to the internal of SSL_CTX
OpenSSL: don't use direct access to the internal of X509_STORE
OpenSSL: don't use direct access to the internal of X509_OBJECT
OpenSSL: don't use direct access to the internal of RSA_METHOD
OpenSSL: don't use direct access to the internal of X509
OpenSSL: don't use direct access to the internal of EVP_PKEY
OpenSSL: don't use direct access to the internal of RSA
OpenSSL: don't use direct access to the internal of DSA
OpenSSL: don't use direct access to the internal of X509_STORE_CTX
OpenSSL: don't use direct access to the internal of EVP_MD_CTX
OpenSSL: don't use direct access to the internal of EVP_CIPHER_CTX
OpenSSL: don't use direct access to the internal of HMAC_CTX
OpenSSL: SSLeay symbols are no longer available in OpenSSL 1.1
OpenSSL: check for the SSL reason, not the full error
OpenSSL: constify getbio() parameters
configure.ac | 37 +++ src/openvpn/crypto.c | 8 +- src/openvpn/crypto_backend.h | 42 +++ src/openvpn/crypto_mbedtls.c | 40 +++ src/openvpn/crypto_openssl.c | 53 +++- src/openvpn/httpdigest.c | 78 ++--- src/openvpn/misc.c | 14 +- src/openvpn/ntlm.c | 12 +- src/openvpn/openssl_compat.h | 609 +++++++++++++++++++++++++++++++++++++++ src/openvpn/openvpn.h | 2 +- src/openvpn/push.c | 11 +- src/openvpn/ssl.c | 38 +-- src/openvpn/ssl_openssl.c | 94 +++--- src/openvpn/ssl_verify_openssl.c | 55 ++-- 14 files changed, 947 insertions(+), 146 deletions(-) create mode 100644 src/openvpn/openssl_compat.h
Signature · 1 line
2.7.4
RFC PATCH 1/15 OpenSSL: don't use direct access to the internal of SSL_CTX
From: Emmanuel Deloget <[email protected]...>
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including SSL_CTX. We have to use the defined functions to do so.
Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
--- configure.ac | 9 ++++++ src/openvpn/openssl_compat.h | 74 ++++++++++++++++++++++++++++++++++++++++++++ src/openvpn/ssl_openssl.c | 13 +++++--- 3 files changed, 91 insertions(+), 5 deletions(-) create mode 100644 src/openvpn/openssl_compat.h
configure.ac +9 -0
@@ -898,6 +898,15 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then [have_crypto_aead_modes="no"; break] ) + AC_CHECK_FUNCS( + [ \ + SSL_CTX_get_default_passwd_cb \ + SSL_CTX_get_default_passwd_cb_userdata \ + ], + , + [] + ) + CFLAGS="${saved_CFLAGS}" LIBS="${saved_LIBS}"
src/openvpn/openssl_compat.h new file +74 -0
74 lines not on this page · raw message
src/openvpn/ssl_openssl.c +8 -5
@@ -45,6 +45,7 @@#include "ssl_backend.h" #include "ssl_common.h" #include "base64.h" +#include "openssl_compat.h" #ifdef ENABLE_CRYPTOAPI #include "cryptoapi.h"
@@ -658,7 +659,8 @@ tls_ctx_load_pkcs12(struct tls_root_ctx *ctx, const char *pkcs12_file, {for (i =0 ; i <sk_X509_num (ca); i++) { -if (!X509_STORE_add_cert (ctx->ctx->cert_store,sk_X509_value (ca, i))) +X509_STORE *cert_store =SSL_CTX_get_cert_store (ctx->ctx); +if (!X509_STORE_add_cert (cert_store,sk_X509_value (ca, i))) {crypto_msg (M_FATAL ,"Cannot add certificate to certificate chain (X509_STORE_add_cert)" ); }
@@ -760,8 +762,9 @@ tls_ctx_load_cert_file_and_copy(struct tls_root_ctx *ctx, goto end; } - x =PEM_read_bio_X509 (in,NULL , ctx->ctx->default_passwd_callback, - ctx->ctx->default_passwd_callback_userdata); + x =PEM_read_bio_X509 (in,NULL , +SSL_CTX_get_default_passwd_cb (ctx->ctx), +SSL_CTX_get_default_passwd_cb_userdata (ctx->ctx));if (x ==NULL ) {SSLerr (SSL_F_SSL_CTX_USE_CERTIFICATE_FILE ,ERR_R_PEM_LIB );
@@ -843,8 +846,8 @@ tls_ctx_load_priv_file(struct tls_root_ctx *ctx, const char *priv_key_file, } pkey =PEM_read_bio_PrivateKey (in,NULL , - ssl_ctx->default_passwd_callback, - ssl_ctx->default_passwd_callback_userdata); +SSL_CTX_get_default_passwd_cb (ctx->ctx), +SSL_CTX_get_default_passwd_cb_userdata (ctx->ctx));if (!pkey) { goto end;
Signature · 1 line
2.7.4
Re: [Openvpn-devel] [RFC PATCH v1 01/15] OpenSSL: don't use direct access to the internal of SSL_CTX
Quoted 153 lines · On 17-02-17 23:00, [email protected]... wrote:
From: Emmanuel Deloget <[email protected]...>
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including
SSL_CTX. We have to use the defined functions to do so.Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
Signed-off-by Emmanuel Deloget <[email protected]...>--- configure.ac | 9 ++++++ src/openvpn/openssl_compat.h | 74 ++++++++++++++++++++++++++++++++++++++++++++ src/openvpn/ssl_openssl.c | 13 +++++--- 3 files changed, 91 insertions(+), 5 deletions(-) create mode 100644 src/openvpn/openssl_compat.hconfigure.ac +9
-0@@ -898,6 +898,15 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then [have_crypto_aead_modes="no"; break] ) + AC_CHECK_FUNCS( + [ \ + SSL_CTX_get_default_passwd_cb \ + SSL_CTX_get_default_passwd_cb_userdata \ + ], + , + [] + ) + CFLAGS="${saved_CFLAGS}" LIBS="${saved_LIBS}"src/openvpn/openssl_compat.h new file +74
-0@@ -0,0 +1,74 @@ +/* +* OpenVPN -- An application to securely tunnel IP networks +* over a single TCP/UDP port, with support for SSL/TLS-based +* session authentication and key exchange, +* packet encryption, packet authentication, and +* packet compression. +* +* Copyright (C) 2002-2017 OpenVPN Technologies, Inc. <[email protected]...> +* Copyright (C) 2010-2017 Fox Crypto B.V. <[email protected]...> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License version 2 +* as published by the Free Software Foundation. +* +* 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 (see the file COPYING included with this +* distribution); if not, write to the Free Software Foundation, Inc., +* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/** +* @file OpenSSL compatibility stub +* +* This file provide compatibility stubs for the OpenSSL libraries +* prior to version 1.1. This version introduces many changes in the +* library interface, including the fact that various objects and +* structures are not fully opaque. +*/ + +#ifndef OPENSSL_COMPAT_H_ +#define OPENSSL_COMPAT_H_ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#elif defined(_MSC_VER) +#include "config-msvc.h" +#endif + +#include <openssl/ssl.h> + +#if !defined(HAVE_SSL_CTX_GET_DEFAULT_PASSWD_CB_USERDATA ) +/** +* Fetch the default password callback user data from the SSL context +* +* @param ctx SSL context +* @return The password callback user data +*/ +static inline void * +SSL_CTX_get_default_passwd_cb_userdata (SSL_CTX *ctx) +{ +return ctx ? ctx->default_passwd_callback_userdata :NULL ; +} +#endif + +#if !defined(HAVE_SSL_CTX_GET_DEFAULT_PASSWD_CB ) +/** +* Fetch the default password callback from the SSL context +* +* @param ctx SSL context +* @return The password callback +*/ +static inline pem_password_cb * +SSL_CTX_get_default_passwd_cb (SSL_CTX *ctx) +{ +return ctx ? ctx->default_passwd_callback :NULL ; +} +#endif + +#endif /* OPENSSL_COMPAT_H_ */ src/openvpn/ssl_openssl.c +6
-3@@ -45,6 +45,7 @@#include "ssl_backend.h" #include "ssl_common.h" #include "base64.h" +#include "openssl_compat.h" #ifdef ENABLE_CRYPTOAPI #include "cryptoapi.h" @@ -658,7 +659,8 @@ tls_ctx_load_pkcs12(struct tls_root_ctx *ctx, const char *pkcs12_file, {for (i =0 ; i <sk_X509_num (ca); i++) { -if (!X509_STORE_add_cert (ctx->ctx->cert_store,sk_X509_value (ca, i))) +X509_STORE *cert_store =SSL_CTX_get_cert_store (ctx->ctx); +if (!X509_STORE_add_cert (cert_store,sk_X509_value (ca, i))) {crypto_msg (M_FATAL ,"Cannot add certificate to certificate chain (X509_STORE_add_cert)" ); }@@ -760,8 +762,9 @@ tls_ctx_load_cert_file_and_copy(struct tls_root_ctx *ctx, goto end; } - x =PEM_read_bio_X509 (in,NULL , ctx->ctx->default_passwd_callback, - ctx->ctx->default_passwd_callback_userdata); + x =PEM_read_bio_X509 (in,NULL , +SSL_CTX_get_default_passwd_cb (ctx->ctx), +SSL_CTX_get_default_passwd_cb_userdata (ctx->ctx));if (x ==NULL ) {SSLerr (SSL_F_SSL_CTX_USE_CERTIFICATE_FILE ,ERR_R_PEM_LIB );
src/openvpn/ssl_openssl.c tls_ctx_load_priv_file(struct tls_root_ctx *ctx, const char *priv_key_file, · line 853
Quoted 10 lines
src/openvpn/ssl_openssl.c +2
-2@@ -843,8 +846,8 @@ tls_ctx_load_priv_file(struct tls_root_ctx *ctx, const char *priv_key_file, } pkey =PEM_read_bio_PrivateKey (in,NULL , - ssl_ctx->default_passwd_callback, - ssl_ctx->default_passwd_callback_userdata); +SSL_CTX_get_default_passwd_cb (ctx->ctx), +SSL_CTX_get_default_passwd_cb_userdata (ctx->ctx));if (!pkey) { goto end;
ACK
-Steffan
[Openvpn-devel] [PATCH applied] Re: OpenSSL: don't use direct access to the internal of SSL_CTX
In reply to [email protected]...Your patch has been applied to the master and release/2.4 branch.
commit 6554ac9fed9c5680f22aa4722e6e07ebf3aa3441 (master) commit b936ddfb631e3a4b219bd035f7110da5679b2d12 (release/2.4)
Author: Emmanuel Deloget Date: Fri Feb 17 23:00:40 2017 +0100
OpenSSL: don't use direct access to the internal of SSL_CTX
Signed-off-by: Emmanuel Deloget <[email protected]...>
Acked-by: Steffan Karger <[email protected]...>
Message-Id: <a77187a66affdba318ef70e0e218b69cdad509d1.1487368114.git.logout@...260...>
URL: https://www.mail-archive.com/[email protected]/msg14088.html
Signed-off-by: Gert Doering <[email protected]...>--
kind regards,
Gert Doering
Re: [Openvpn-devel] [RFC PATCH v1 01/15] OpenSSL: don't use direct access to the internal of SSL_CTX
In reply to [email protected]...Good morning,
Quoted 6 lines · On Fri, Feb 17, 2017 at 11:00:40PM +0100, [email protected]... wrote:
From: Emmanuel Deloget <[email protected]...>
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including
SSL_CTX. We have to use the defined functions to do so.
Quoted 7 lines
Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
Signed-off-by Emmanuel Deloget <[email protected]...>--- configure.ac | 9 ++++++ src/openvpn/openssl_compat.h | 74 ++++++++++++++++++++++++++++++++++++++++++++
This patch brings two problems outside the "OpenSSL functionality" part.
- openssl_compat.h is not included in the built tarballs, so mingw builds fail (and "builds for anyone building from tarballs" would break) -> findable by running "make distcheck"
- configure.ac does something to CentOS 6 / RHEL 6 which makes configure explode:
...
checking for linux/if_tun.h... yes
checking tap-windows.h usability... no
checking tap-windows.h presence... no
checking for tap-windows.h... no
checking whether TUNSETPERSIST is declared... yes checking for setcon in -lselinux... yes
checking for pam_start in -lpam... yes
checking for PKCS11_HELPER... no
./configure: line 21440: syntax error near unexpected token fi' ./configure: line 21440: fi'
The first one is easily fixed, but I do not know how to tackle the second one - no access to a CentOS6/RHEL6 box, and not enough autoconf clue to see this right away. Patch *looks* good... most likely just a stray "\" where none should be, or so...
Please :-)
gert
Signature · 4 lines
USENET is *not* the non-clickable part of WWW!
//www.muc.de/~gert/
Gert Doering - Munich, Germany [email protected]...
fax: +49-89-35655025 [email protected]...Re: [Openvpn-devel] [RFC PATCH v1 01/15] OpenSSL: don't use direct access to the internal of SSL_CTX
Hi,
Quoted 6 lines · Gert Doering
This patch brings two problems outside the "OpenSSL functionality" part.
-
openssl_compat.his not included in the built tarballs, so mingw builds fail (and "builds for anyone building from tarballs" would break) -> findable by running "make distcheck"
This has been fixed & pushed (so we can build windows snapshots again).
Quoted 14 lines
- configure.ac does something to CentOS 6 / RHEL 6 which makes configure explode:
...
checking forlinux/if_tun.h... yes
checkingtap-windows.husability... no
checkingtap-windows.hpresence... no
checking fortap-windows.h... no
checking whether TUNSETPERSIST is declared... yes checking for setcon in -lselinux... yes
checking forpam_startin -lpam... yes
checking forPKCS11_HELPER... no
./configure: line 21440: syntax error near unexpected tokenfi' ./configure: line 21440:fi'
This still needs investigation.
gert
Signature · 4 lines
USENET is *not* the non-clickable part of WWW!
//www.muc.de/~gert/
Gert Doering - Munich, Germany [email protected]...
fax: +49-89-35655025 [email protected]...Re: [Openvpn-devel] [RFC PATCH v1 01/15] OpenSSL: don't use direct access to the internal of SSL_CTX
Hello,
Quoted 27 lines · Gert Doering
Hi,
Quoted 6 lines · Gert Doering
This patch brings two problems outside the "OpenSSL functionality" part.
-
openssl_compat.his not included in the built tarballs, so mingw builds fail (and "builds for anyone building from tarballs" would break) -> findable by running "make distcheck"This has been fixed & pushed (so we can build windows snapshots again).
Quoted 14 lines
- configure.ac does something to CentOS 6 / RHEL 6 which makes configure explode:
...
checking forlinux/if_tun.h... yes
checkingtap-windows.husability... no
checkingtap-windows.hpresence... no
checking fortap-windows.h... no
checking whether TUNSETPERSIST is declared... yes checking for setcon in -lselinux... yes
checking forpam_startin -lpam... yes
checking forPKCS11_HELPER... no
./configure: line 21440: syntax error near unexpected tokenfi' ./configure: line 21440:fi'
Quoted 1 line
This still needs investigation.
I'm taking the time to install a CentOS 6 on a VM. I'll test this asap.
Best regards,
-- Emmanuel Deloget
Re: [Openvpn-devel] [RFC PATCH v1 01/15] OpenSSL: don't use direct access to the internal of SSL_CTX
Quoted 15 lines · Emmanuel Deloget
Quoted 15 lines
Quoted 14 lines
- configure.ac does something to CentOS 6 / RHEL 6 which makes configure explode:
...
checking forlinux/if_tun.h... yes
checkingtap-windows.husability... no
checkingtap-windows.hpresence... no
checking fortap-windows.h... no
checking whether TUNSETPERSIST is declared... yes checking for setcon in -lselinux... yes
checking forpam_startin -lpam... yes
checking forPKCS11_HELPER... no
./configure: line 21440: syntax error near unexpected tokenfi' ./configure: line 21440:fi'
Quoted 3 lines
Quoted 1 line
This still needs investigation.
I'm taking the time to install a CentOS 6 on a VM. I'll test this asap.
I have a fix ready, but am busy with testing it on various platforms.
-Steffan
PATCH 1/1 OpenSSL: 1.1 fallout - fix configure on old autoconf
In reply to Gert DoeringOlder versions of autoconf generate an empty "else fi" block for empty fields in an AC_CHECK_FUNCS() macro. This breaks on e.g. RHEL6.
--- configure.ac | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
configure.ac +1 -3
@@ -912,9 +912,7 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then X509_STORE_get0_objects \ X509_OBJECT_free \ X509_OBJECT_get_type \ - ], - , - [] + ] ) CFLAGS="${saved_CFLAGS}"
Signature · 1 line
2.7.4
[Openvpn-devel] [PATCH applied] Re: OpenSSL: 1.1 fallout - fix configure on old autoconf
ACK, thanks.
Your patch has been applied to the master and release/2.4 branch.
commit 07372a0fdeb3638204d197d0614f776a0eb73ab9 (master) commit b97a5cc044dc6db3f0e1f9f06a6f5da522f0a33a (release/2.4)
Author: Steffan Karger Date: Thu Feb 23 11:35:38 2017 +0100
OpenSSL: 1.1 fallout - fix configure on old autoconf
Signed-off-by: Steffan Karger <[email protected]...>
Acked-by: Gert Doering <[email protected]...>
Message-Id: <[email protected]...>
URL: http://www.mail-archive.com/search?l=mid&[email protected]...
Signed-off-by: Gert Doering <[email protected]...>--
kind regards,
Gert Doering
RFC PATCH 2/15 OpenSSL: don't use direct access to the internal of X509_STORE
In reply to [email protected]...From: Emmanuel Deloget <[email protected]...>
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including X509_STORE. We have to use the defined functions to do so.
Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
--- configure.ac | 1 + src/openvpn/openssl_compat.h | 15 +++++++++++++++ src/openvpn/ssl_openssl.c | 7 ++++--- src/openvpn/ssl_verify_openssl.c | 6 ++++-- 4 files changed, 24 insertions(+), 5 deletions(-)
configure.ac +1 -0
@@ -902,6 +902,7 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then [ \ SSL_CTX_get_default_passwd_cb \ SSL_CTX_get_default_passwd_cb_userdata \ + X509_STORE_get0_objects \ ], , []
src/openvpn/openssl_compat.h +15 -0
@@ -42,6 +42,7 @@#endif #include <openssl/ssl.h> +#include <openssl/x509.h> #if !defined(HAVE_SSL_CTX_GET_DEFAULT_PASSWD_CB_USERDATA )/**
@@ -71,4 +72,18 @@ SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx) }#endif +#if !defined(HAVE_X509_STORE_GET0_OBJECTS ) +/** +* Fetch the X509 object stack from the X509 store +* +* @param store X509 object store +* @return the X509 object stack +*/ +static inline STACK_OF (X509_OBJECT) * +X509_STORE_get0_objects (X509_STORE *store) +{ +return store ? store->objs :NULL ; +} +#endif +#endif /* OPENSSL_COMPAT_H_ */
src/openvpn/ssl_openssl.c +4 -3
@@ -900,13 +900,14 @@ backend_tls_ctx_reload_crl(struct tls_root_ctx *ssl_ctx, const char *crl_file,/* Always start with a cleared CRL list, for that we * we need to manually find the CRL object from the stack * and remove it */ -for (int i =0 ; i <sk_X509_OBJECT_num (store->objs); i++) +STACK_OF (X509_OBJECT) *objs =X509_STORE_get0_objects (store); +for (int i =0 ; i <sk_X509_OBJECT_num (objs); i++) { -X509_OBJECT *obj =sk_X509_OBJECT_value (store->objs, i); +X509_OBJECT *obj =sk_X509_OBJECT_value (objs, i);ASSERT (obj);if (obj->type ==X509_LU_CRL ) { -sk_X509_OBJECT_delete (store->objs, i); +sk_X509_OBJECT_delete (objs, i);X509_OBJECT_free_contents (obj);OPENSSL_free (obj); }
src/openvpn/ssl_verify_openssl.c +4 -2
@@ -43,6 +43,7 @@#include "ssl_openssl.h" #include "ssl_verify.h" #include "ssl_verify_backend.h" +#include "openssl_compat.h" #include <openssl/x509v3.h> #include <openssl/err.h>
@@ -715,9 +716,10 @@ tls_verify_crl_missing(const struct tls_options *opt)crypto_msg (M_FATAL ,"Cannot get certificate store" ); } -for (int i =0 ; i <sk_X509_OBJECT_num (store->objs); i++) +STACK_OF (X509_OBJECT ) *objs =X509_STORE_get0_objects (store); +for (int i =0 ; i <sk_X509_OBJECT_num (objs); i++) { -X509_OBJECT *obj =sk_X509_OBJECT_value (store->objs, i); +X509_OBJECT *obj =sk_X509_OBJECT_value (objs, i);ASSERT (obj);if (obj->type ==X509_LU_CRL ) {
Signature · 1 line
2.7.4
Re: [Openvpn-devel] [RFC PATCH v1 02/15] OpenSSL: don't use direct access to the internal of X509_STORE
Quoted 98 lines · On 17-02-17 23:00, [email protected]... wrote:
From: Emmanuel Deloget <[email protected]...>
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including
X509_STORE. We have to use the defined functions to do so.Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
Signed-off-by Emmanuel Deloget <[email protected]...>--- configure.ac | 1 + src/openvpn/openssl_compat.h | 15 +++++++++++++++ src/openvpn/ssl_openssl.c | 7 ++++--- src/openvpn/ssl_verify_openssl.c | 6 ++++-- 4 files changed, 24 insertions(+), 5 deletions(-)configure.ac +1
-0@@ -902,6 +902,7 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then [ \ SSL_CTX_get_default_passwd_cb \ SSL_CTX_get_default_passwd_cb_userdata \ + X509_STORE_get0_objects \ ], , []src/openvpn/openssl_compat.h +15
-0@@ -42,6 +42,7 @@#endif #include <openssl/ssl.h> +#include <openssl/x509.h> #if !defined(HAVE_SSL_CTX_GET_DEFAULT_PASSWD_CB_USERDATA )/** @@ -71,4 +72,18 @@ SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx) }#endif +#if !defined(HAVE_X509_STORE_GET0_OBJECTS ) +/** +* Fetch the X509 object stack from the X509 store +* +* @param store X509 object store +* @return the X509 object stack +*/ +static inline STACK_OF (X509_OBJECT) * +X509_STORE_get0_objects (X509_STORE *store) +{ +return store ? store->objs :NULL ; +} +#endif +#endif /* OPENSSL_COMPAT_H_ */ src/openvpn/ssl_openssl.c +4
-3@@ -900,13 +900,14 @@ backend_tls_ctx_reload_crl(struct tls_root_ctx *ssl_ctx, const char *crl_file,/* Always start with a cleared CRL list, for that we * we need to manually find the CRL object from the stack * and remove it */ -for (int i =0 ; i <sk_X509_OBJECT_num (store->objs); i++) +STACK_OF (X509_OBJECT) *objs =X509_STORE_get0_objects (store); +for (int i =0 ; i <sk_X509_OBJECT_num (objs); i++) { -X509_OBJECT *obj =sk_X509_OBJECT_value (store->objs, i); +X509_OBJECT *obj =sk_X509_OBJECT_value (objs, i);ASSERT (obj);if (obj->type ==X509_LU_CRL ) { -sk_X509_OBJECT_delete (store->objs, i); +sk_X509_OBJECT_delete (objs, i);X509_OBJECT_free_contents (obj);OPENSSL_free (obj); }src/openvpn/ssl_verify_openssl.c +1
-0@@ -43,6 +43,7 @@#include "ssl_openssl.h" #include "ssl_verify.h" #include "ssl_verify_backend.h" +#include "openssl_compat.h" #include <openssl/x509v3.h> #include <openssl/err.h> @@ -715,9 +716,10 @@ tls_verify_crl_missing(const struct tls_options *opt)crypto_msg (M_FATAL ,"Cannot get certificate store" ); }
src/openvpn/ssl_verify_openssl.c tls_verify_crl_missing(const struct tls_options *opt) · line 725
Quoted 10 lines
src/openvpn/ssl_verify_openssl.c +3
-2-for (int i =0 ; i <sk_X509_OBJECT_num (store->objs); i++) +STACK_OF (X509_OBJECT) *objs =X509_STORE_get0_objects (store); +for (int i =0 ; i <sk_X509_OBJECT_num (objs); i++) { -X509_OBJECT *obj =sk_X509_OBJECT_value (store->objs, i); +X509_OBJECT *obj =sk_X509_OBJECT_value (objs, i);ASSERT (obj);if (obj->type ==X509_LU_CRL ) {
ACK
-Steffan
[Openvpn-devel] [PATCH applied] Re: OpenSSL: don't use direct access to the internal of X509_STORE
In reply to [email protected]...Your patch has been applied to the master and release/2.4 branch.
commit f05665df4150c6a345eec5432a02fd799bea0f2c (master) commit 24bca7bee2ee5c48880a197ce9727bbc5a0149e5 (release/2.4)
Author: Emmanuel Deloget Date: Fri Feb 17 23:00:41 2017 +0100
OpenSSL: don't use direct access to the internal of X509_STORE
Signed-off-by: Emmanuel Deloget <[email protected]...>
Acked-by: Steffan Karger <[email protected]...>
Message-Id: <8e6d66e3a9a40abb3d7c99c48ba59bad1037d0ef.1487368114.git.logout@...260...>
URL: https://www.mail-archive.com/[email protected]/msg14076.html
Signed-off-by: Gert Doering <[email protected]...>--
kind regards,
Gert Doering
RFC PATCH 3/15 OpenSSL: don't use direct access to the internal of X509_OBJECT
In reply to [email protected]...From: Emmanuel Deloget <[email protected]...>
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including X509_OBJECT. We have to use the defined functions to do so.
Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
--- configure.ac | 2 ++ src/openvpn/openssl_compat.h | 31 +++++++++++++++++++++++++++++++ src/openvpn/ssl_openssl.c | 5 ++--- src/openvpn/ssl_verify_openssl.c | 2 +- 4 files changed, 36 insertions(+), 4 deletions(-)
configure.ac +2 -0
@@ -903,6 +903,8 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then SSL_CTX_get_default_passwd_cb \ SSL_CTX_get_default_passwd_cb_userdata \ X509_STORE_get0_objects \ + X509_OBJECT_free \ + X509_OBJECT_get_type \ ], , []
src/openvpn/openssl_compat.h +31 -0
@@ -86,4 +86,35 @@ X509_STORE_get0_objects(X509_STORE *store) }#endif +#if !defined(HAVE_X509_OBJECT_FREE ) +/** +* Destroy a X509 object +* +* @param obj X509 object +*/ +static inline void +X509_OBJECT_free (X509_OBJECT *obj) +{ +if (obj) + { +X509_OBJECT_free_contents (obj); +OPENSSL_free (obj); + } +} +#endif + +#if !defined(HAVE_X509_OBJECT_GET_TYPE ) +/** +* Get the type of an X509 object +* +* @param obj X509 object +* @return The underlying object type +*/ +static inline int +X509_OBJECT_get_type (const X509_OBJECT *obj) +{ +return obj ? obj->type :X509_LU_FAIL ; +} +#endif +#endif /* OPENSSL_COMPAT_H_ */
src/openvpn/ssl_openssl.c +2 -3
@@ -905,11 +905,10 @@ backend_tls_ctx_reload_crl(struct tls_root_ctx *ssl_ctx, const char *crl_file, {X509_OBJECT *obj =sk_X509_OBJECT_value (objs, i);ASSERT (obj); -if (obj->type ==X509_LU_CRL ) +if (X509_OBJECT_get_type (obj) ==X509_LU_CRL ) {sk_X509_OBJECT_delete (objs, i); -X509_OBJECT_free_contents (obj); -OPENSSL_free (obj); +X509_OBJECT_free (obj); } }
src/openvpn/ssl_verify_openssl.c +1 -1
@@ -721,7 +721,7 @@ tls_verify_crl_missing(const struct tls_options *opt) {X509_OBJECT *obj =sk_X509_OBJECT_value (objs, i);ASSERT (obj); -if (obj->type ==X509_LU_CRL ) +if (X509_OBJECT_get_type (obj) ==X509_LU_CRL ) {return false; }
Signature · 1 line
2.7.4
Re: [Openvpn-devel] [RFC PATCH v1 03/15] OpenSSL: don't use direct access to the internal of X509_OBJECT
Quoted 94 lines · On 17-02-17 23:00, [email protected]... wrote:
From: Emmanuel Deloget <[email protected]...>
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including
X509_OBJECT. We have to use the defined functions to do so.Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
Signed-off-by Emmanuel Deloget <[email protected]...>--- configure.ac | 2 ++ src/openvpn/openssl_compat.h | 31 +++++++++++++++++++++++++++++++ src/openvpn/ssl_openssl.c | 5 ++--- src/openvpn/ssl_verify_openssl.c | 2 +- 4 files changed, 36 insertions(+), 4 deletions(-)configure.ac +2
-0@@ -903,6 +903,8 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then SSL_CTX_get_default_passwd_cb \ SSL_CTX_get_default_passwd_cb_userdata \ X509_STORE_get0_objects \ + X509_OBJECT_free \ + X509_OBJECT_get_type \ ], , []src/openvpn/openssl_compat.h +31
-0@@ -86,4 +86,35 @@ X509_STORE_get0_objects(X509_STORE *store) }#endif +#if !defined(HAVE_X509_OBJECT_FREE ) +/** +* Destroy a X509 object +* +* @param obj X509 object +*/ +static inline void +X509_OBJECT_free (X509_OBJECT *obj) +{ +if (obj) + { +X509_OBJECT_free_contents (obj); +OPENSSL_free (obj); + } +} +#endif + +#if !defined(HAVE_X509_OBJECT_GET_TYPE ) +/** +* Get the type of an X509 object +* +* @param obj X509 object +* @return The underlying object type +*/ +static inline int +X509_OBJECT_get_type (const X509_OBJECT *obj) +{ +return obj ? obj->type :X509_LU_FAIL ; +} +#endif +#endif /* OPENSSL_COMPAT_H_ */ src/openvpn/ssl_openssl.c +2
-3@@ -905,11 +905,10 @@ backend_tls_ctx_reload_crl(struct tls_root_ctx *ssl_ctx, const char *crl_file, {X509_OBJECT *obj =sk_X509_OBJECT_value (objs, i);ASSERT (obj); -if (obj->type ==X509_LU_CRL ) +if (X509_OBJECT_get_type (obj) ==X509_LU_CRL ) {sk_X509_OBJECT_delete (objs, i); -X509_OBJECT_free_contents (obj); -OPENSSL_free (obj); +X509_OBJECT_free (obj); } }src/openvpn/ssl_verify_openssl.c +0
-0
src/openvpn/ssl_verify_openssl.c tls_verify_crl_missing(const struct tls_options *opt) · line 727
Quoted 8 lines
src/openvpn/ssl_verify_openssl.c +1
-1@@ -721,7 +721,7 @@ tls_verify_crl_missing(const struct tls_options *opt) {X509_OBJECT *obj =sk_X509_OBJECT_value (objs, i);ASSERT (obj); -if (obj->type ==X509_LU_CRL ) +if (X509_OBJECT_get_type (obj) ==X509_LU_CRL ) {return false; }
ACK
-Steffan
[Openvpn-devel] [PATCH applied] Re: OpenSSL: don't use direct access to the internal of X509_OBJECT
In reply to [email protected]...Your patch has been applied to the master and release/2.4 branch.
commit 47191f49890ee5c53fa78a8ce9bf96b9c8d27a82 (master) commit d782597ede843266fd2c7854a6f90ec7ce4bb92b (release/2.4)
Author: Emmanuel Deloget Date: Fri Feb 17 23:00:42 2017 +0100
OpenSSL: don't use direct access to the internal of X509_OBJECT
Signed-off-by: Emmanuel Deloget <[email protected]...>
Acked-by: Steffan Karger <[email protected]...>
Message-Id: <c849c9778d2b2faa4eb4d31367b37d993da5eb85.1487368114.git.logout@...260...>
URL: https://www.mail-archive.com/[email protected]/msg14080.html
Signed-off-by: Gert Doering <[email protected]...>--
kind regards,
Gert Doering
RFC PATCH 4/15 OpenSSL: don't use direct access to the internal of RSA_METHOD
In reply to [email protected]...From: Emmanuel Deloget <[email protected]...>
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including RSA_METHOD. We have to use the defined functions to do so.
Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
--- configure.ac | 9 +++ src/openvpn/openssl_compat.h | 186 +++++++++++++++++++++++++++++++++++++++++++ src/openvpn/ssl_openssl.c | 22 ++--- 3 files changed, 206 insertions(+), 11 deletions(-)
configure.ac +9 -0
@@ -905,6 +905,15 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then X509_STORE_get0_objects \ X509_OBJECT_free \ X509_OBJECT_get_type \ + RSA_meth_new \ + RSA_meth_free \ + RSA_meth_set_pub_enc \ + RSA_meth_set_pub_dec \ + RSA_meth_set_priv_enc \ + RSA_meth_set_priv_dec \ + RSA_meth_set_init \ + RSA_meth_set_finish \ + RSA_meth_set0_app_data \ ], , []
src/openvpn/openssl_compat.h +186 -0
196 lines not on this page · raw message
src/openvpn/ssl_openssl.c +11 -11
@@ -978,7 +978,7 @@ rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, istatic int rsa_finish (RSA *rsa) { -free ((void *)rsa->meth); +RSA_meth_free (rsa->meth); rsa->meth =NULL ;return 1 ; }
@@ -1053,16 +1053,16 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx,ASSERT (NULL != cert);/* allocate custom RSA method object */ -ALLOC_OBJ_CLEAR (rsa_meth,RSA_METHOD ); - rsa_meth->name ="OpenVPN external private key RSA Method" ; - rsa_meth->rsa_pub_enc = rsa_pub_enc; - rsa_meth->rsa_pub_dec = rsa_pub_dec; - rsa_meth->rsa_priv_enc = rsa_priv_enc; - rsa_meth->rsa_priv_dec = rsa_priv_dec; - rsa_meth->init =NULL ; - rsa_meth->finish = rsa_finish; - rsa_meth->flags =RSA_METHOD_FLAG_NO_CHECK ; - rsa_meth->app_data =NULL ; + rsa_meth =RSA_meth_new ("OpenVPN external private key RSA Method" , +RSA_METHOD_FLAG_NO_CHECK ); +check_malloc_return (rsa_meth); +RSA_meth_set_pub_enc (rsa_meth, rsa_pub_enc); +RSA_meth_set_pub_dec (rsa_meth, rsa_pub_dec); +RSA_meth_set_priv_enc (rsa_meth, rsa_priv_enc); +RSA_meth_set_priv_dec (rsa_meth, rsa_priv_dec); +RSA_meth_set_init (rsa_meth,NULL ); +RSA_meth_set_finish (rsa_meth, rsa_finish); +RSA_meth_set0_app_data (rsa_meth,NULL );/* allocate RSA object */ rsa =RSA_new ();
Signature · 1 line
2.7.4
Re: [Openvpn-devel] [RFC PATCH v1 04/15] OpenSSL: don't use direct access to the internal of RSA_METHOD
Hi,
Quoted 74 lines · On 17-02-17 23:00, [email protected]... wrote:
From: Emmanuel Deloget <[email protected]...>
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including
RSA_METHOD. We have to use the defined functions to do so.Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
Signed-off-by Emmanuel Deloget <[email protected]...>--- configure.ac | 9 +++ src/openvpn/openssl_compat.h | 186 +++++++++++++++++++++++++++++++++++++++++++ src/openvpn/ssl_openssl.c | 22 ++--- 3 files changed, 206 insertions(+), 11 deletions(-)configure.ac +9
-0@@ -905,6 +905,15 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then X509_STORE_get0_objects \ X509_OBJECT_free \ X509_OBJECT_get_type \ + RSA_meth_new \ + RSA_meth_free \ + RSA_meth_set_pub_enc \ + RSA_meth_set_pub_dec \ + RSA_meth_set_priv_enc \ + RSA_meth_set_priv_dec \ + RSA_meth_set_init \ + RSA_meth_set_finish \ + RSA_meth_set0_app_data \ ], , []src/openvpn/openssl_compat.h +23
-0@@ -41,6 +41,8 @@#include "config-msvc.h" #endif +#include "buffer.h" +#include <openssl/ssl.h> #include <openssl/x509.h> @@ -117,4 +119,188 @@ X509_OBJECT_get_type(const X509_OBJECT *obj) }#endif +#if !defined(HAVE_RSA_METH_NEW ) +/** +* Allocate a new RSA method object +* +* @param name The object name +* @param flags Configuration flags +* @return A new RSA method object +*/ +static inline RSA_METHOD * +RSA_meth_new (const char *name,int flags) +{ +RSA_METHOD *rsa_meth =NULL ; +ALLOC_OBJ_CLEAR (rsa_meth,RSA_METHOD ); + rsa_meth->name = name; + rsa_meth->flags = flags; +return rsa_meth; +} +#endif + +#if !defined(HAVE_RSA_METH_FREE ) +/**
src/openvpn/openssl_compat.h X509_OBJECT_get_type(const X509_OBJECT *obj) · line 152
Quoted 10 lines
src/openvpn/openssl_compat.h +10
-0+* Free an existing RSA_METHOD object +* +* @param meth The RSA_METHOD object +*/ +static inline void +RSA_meth_free (RSA_METHOD *meth) +{ +free (meth); +} +#endif
I think it would be nicer to more closely mimic the 1.1 behaviour in RSA_meth_{new,free}(), and copy the name string in new() and free it again in free(). That could prevent a future use-after-free that would occur for pre-1.1.0, but not 1.1.0+:
char *mystring = calloc(50, 1);
RSA_METHOD *meth = RSA_meth_new(mystring, 0);
free(mystring);
meth.smoke();
^^ might cause problems(Hint: use string_alloc(x, NULL).)
Quoted 159 lines
src/openvpn/openssl_compat.h +153
-0+ +#if !defined(HAVE_RSA_METH_SET_PUB_ENC ) +/** +* Set the public encoding function of an RSA_METHOD object +* +* @param meth The RSA_METHOD object +* @param pub_enc the public encoding function +* @return 1 on success, 0 on error +*/ +static inline int +RSA_meth_set_pub_enc (RSA_METHOD *meth, +int (*pub_enc) (int flen,const unsigned char *from, +unsigned char *to,RSA *rsa, +int padding)) +{ +if (meth) + { + meth->rsa_pub_enc = pub_enc; +return 1 ; + } +return 0 ; +} +#endif + +#if !defined(HAVE_RSA_METH_SET_PUB_DEC ) +/** +* Set the public decoding function of an RSA_METHOD object +* +* @param meth The RSA_METHOD object +* @param pub_dec the public decoding function +* @return 1 on success, 0 on error +*/ +static inline int +RSA_meth_set_pub_dec (RSA_METHOD *meth, +int (*pub_dec) (int flen,const unsigned char *from, +unsigned char *to,RSA *rsa, +int padding)) +{ +if (meth) + { + meth->rsa_pub_dec = pub_dec; +return 1 ; + } +return 0 ; +} +#endif + +#if !defined(HAVE_RSA_METH_SET_PRIV_ENC ) +/** +* Set the private encoding function of an RSA_METHOD object +* +* @param meth The RSA_METHOD object +* @param priv_enc the private encoding function +* @return 1 on success, 0 on error +*/ +static inline int +RSA_meth_set_priv_enc (RSA_METHOD *meth, +int (*priv_enc) (int flen,const unsigned char *from, +unsigned char *to,RSA *rsa, +int padding)) +{ +if (meth) + { + meth->rsa_priv_enc = priv_enc; +return 1 ; + } +return 0 ; +} +#endif + +#if !defined(HAVE_RSA_METH_SET_PRIV_DEC ) +/** +* Set the private decoding function of an RSA_METHOD object +* +* @param meth The RSA_METHOD object +* @param priv_dec the private decoding function +* @return 1 on success, 0 on error +*/ +static inline int +RSA_meth_set_priv_dec (RSA_METHOD *meth, +int (*priv_dec) (int flen,const unsigned char *from, +unsigned char *to,RSA *rsa, +int padding)) +{ +if (meth) + { + meth->rsa_priv_dec = priv_dec; +return 1 ; + } +return 0 ; +} +#endif + +#if !defined(HAVE_RSA_METH_SET_INIT ) +/** +* Set the init function of an RSA_METHOD object +* +* @param meth The RSA_METHOD object +* @param init the init function +* @return 1 on success, 0 on error +*/ +static inline int +RSA_meth_set_init (RSA_METHOD *meth,int (*init) (RSA *rsa)) +{ +if (meth) + { + meth->init = init; +return 1 ; + } +return 0 ; +} +#endif + +#if !defined(HAVE_RSA_METH_SET_FINISH ) +/** +* Set the finish function of an RSA_METHOD object +* +* @param meth The RSA_METHOD object +* @param finish the finish function +* @return 1 on success, 0 on error +*/ +static inline int +RSA_meth_set_finish (RSA_METHOD *meth,int (*finish) (RSA *rsa)) +{ +if (meth) + { + meth->finish = finish; +return 1 ; + } +return 0 ; +} +#endif + +#if !defined(HAVE_RSA_METH_SET0_APP_DATA ) +/** +* Set the application data of an RSA_METHOD object +* +* @param meth The RSA_METHOD object +* @param app_data Application data +* @return 1 on success, 0 on error +*/ +static inline int +RSA_meth_set0_app_data (RSA_METHOD *meth,void *app_data) +{ +if (meth) + { + meth->app_data = app_data; +return 1 ; + } +return 0 ; +} +#endif +#endif /* OPENSSL_COMPAT_H_ */ src/openvpn/ssl_openssl.c +0
-0
src/openvpn/ssl_openssl.c rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, i · line 984
Quoted 8 lines
src/openvpn/ssl_openssl.c +1
-1@@ -978,7 +978,7 @@ rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, istatic int rsa_finish (RSA *rsa) { -free ((void *)rsa->meth); +RSA_meth_free (rsa->meth); rsa->meth =NULL ;return 1 ; }
This change still works, but he follow up change in this method in 07/15 causes problems:
static int
rsa_finish(RSA *rsa)
{
- RSA_meth_free(rsa->meth);
- rsa->meth = NULL;
+ RSA_METHOD *meth = (RSA_METHOD *)RSA_get_method(rsa);
+ RSA_meth_free(meth);
+ RSA_set_method(rsa, NULL);
return 1;
}Casting away const on the object returned by RSA_get_method() is a smell, but it really fails because RSA_set_method(rsa, NULL) calls rsa->meth->finish(), which is implemented by this very function. That means that RSA_meth_free() will perform a double free on meth->name.
I briefly looked into a fix, but didn't immediately see a nice solution here. At least the RSA_set_method(rsa, RSA_get_default_method()) doesn't work either, because you'll end up with rsa_finish() and RSA_set_method() calling each other infinitely...
(Noting this here, because the fix for 07 might cause changes to this patch too.)
Quoted 18 lines
src/openvpn/ssl_openssl.c +3
-10@@ -1053,16 +1053,16 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx,ASSERT (NULL != cert);/* allocate custom RSA method object */ -ALLOC_OBJ_CLEAR (rsa_meth,RSA_METHOD ); - rsa_meth->name ="OpenVPN external private key RSA Method" ; - rsa_meth->rsa_pub_enc = rsa_pub_enc; - rsa_meth->rsa_pub_dec = rsa_pub_dec; - rsa_meth->rsa_priv_enc = rsa_priv_enc; - rsa_meth->rsa_priv_dec = rsa_priv_dec; - rsa_meth->init =NULL ; - rsa_meth->finish = rsa_finish; - rsa_meth->flags =RSA_METHOD_FLAG_NO_CHECK ; - rsa_meth->app_data =NULL ; + rsa_meth =RSA_meth_new ("OpenVPN external private key RSA Method" , +RSA_METHOD_FLAG_NO_CHECK ); +check_malloc_return (rsa_meth);
src/openvpn/ssl_openssl.c tls_ctx_use_external_private_key(struct tls_root_ctx *ctx, · line 1068
Quoted 10 lines
src/openvpn/ssl_openssl.c +7
-0+RSA_meth_set_pub_enc (rsa_meth, rsa_pub_enc); +RSA_meth_set_pub_dec (rsa_meth, rsa_pub_dec); +RSA_meth_set_priv_enc (rsa_meth, rsa_priv_enc); +RSA_meth_set_priv_dec (rsa_meth, rsa_priv_dec); +RSA_meth_set_init (rsa_meth,NULL ); +RSA_meth_set_finish (rsa_meth, rsa_finish); +RSA_meth_set0_app_data (rsa_meth,NULL );/* allocate RSA object */ rsa =RSA_new ();
-Steffan
Re: [Openvpn-devel] [RFC PATCH v1 04/15] OpenSSL: don't use direct access to the internal of RSA_METHOD
Hi Steffan,
Quoted 84 lines · Steffan Karger
Hi,
Quoted 81 lines · On 17-02-17 23:00, [email protected]... wrote:
From: Emmanuel Deloget <[email protected]...>
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including
RSA_METHOD. We have to use the defined functions to do so.Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
Signed-off-by Emmanuel Deloget <[email protected]...>--- configure.ac | 9 +++ src/openvpn/openssl_compat.h | 186 +++++++++++++++++++++++++++++++++++++++++++ src/openvpn/ssl_openssl.c | 22 ++--- 3 files changed, 206 insertions(+), 11 deletions(-)configure.ac +9
-0@@ -905,6 +905,15 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then X509_STORE_get0_objects \ X509_OBJECT_free \ X509_OBJECT_get_type \ + RSA_meth_new \ + RSA_meth_free \ + RSA_meth_set_pub_enc \ + RSA_meth_set_pub_dec \ + RSA_meth_set_priv_enc \ + RSA_meth_set_priv_dec \ + RSA_meth_set_init \ + RSA_meth_set_finish \ + RSA_meth_set0_app_data \ ], , []src/openvpn/openssl_compat.h +30
-0@@ -41,6 +41,8 @@#include "config-msvc.h" #endif +#include "buffer.h" +#include <openssl/ssl.h> #include <openssl/x509.h> @@ -117,4 +119,188 @@ X509_OBJECT_get_type(const X509_OBJECT *obj) }#endif +#if !defined(HAVE_RSA_METH_NEW ) +/** +* Allocate a new RSA method object +* +* @param name The object name +* @param flags Configuration flags +* @return A new RSA method object +*/ +static inline RSA_METHOD * +RSA_meth_new (const char *name,int flags) +{ +RSA_METHOD *rsa_meth =NULL ; +ALLOC_OBJ_CLEAR (rsa_meth,RSA_METHOD ); + rsa_meth->name = name; + rsa_meth->flags = flags; +return rsa_meth; +} +#endif + +#if !defined(HAVE_RSA_METH_FREE ) +/** +* Free an existing RSA_METHOD object +* +* @param meth The RSA_METHOD object +*/ +static inline void +RSA_meth_free (RSA_METHOD *meth) +{
Quoted 8 lines
src/openvpn/openssl_compat.h X509_OBJECT_get_type(const X509_OBJECT *obj) · line 152
Quoted 3 lines
src/openvpn/openssl_compat.h +3
-0+ free(meth); +} +#endif I think it would be nicer to more closely mimic the 1.1 behaviour in RSA_meth_{new,free}(), and copy the name string in
new()and free it again infree(). That could prevent a future use-after-free that would occur for pre-1.1.0, but not 1.1.0+:
I failed to see that when I implemented my solution. I'll give a look as soon as possible.
Quoted 196 lines
char *mystring = calloc(50, 1); RSA_METHOD *meth = RSA_meth_new(mystring, 0); free(mystring); meth.smoke(); ^^ might cause problems(Hint: use
string_alloc(x, NULL).)Quoted 159 lines
src/openvpn/openssl_compat.h +153
-0+ +#if !defined(HAVE_RSA_METH_SET_PUB_ENC ) +/** +* Set the public encoding function of an RSA_METHOD object +* +* @param meth The RSA_METHOD object +* @param pub_enc the public encoding function +* @return 1 on success, 0 on error +*/ +static inline int +RSA_meth_set_pub_enc (RSA_METHOD *meth, +int (*pub_enc) (int flen,const unsigned char *from, +unsigned char *to,RSA *rsa, +int padding)) +{ +if (meth) + { + meth->rsa_pub_enc = pub_enc; +return 1 ; + } +return 0 ; +} +#endif + +#if !defined(HAVE_RSA_METH_SET_PUB_DEC ) +/** +* Set the public decoding function of an RSA_METHOD object +* +* @param meth The RSA_METHOD object +* @param pub_dec the public decoding function +* @return 1 on success, 0 on error +*/ +static inline int +RSA_meth_set_pub_dec (RSA_METHOD *meth, +int (*pub_dec) (int flen,const unsigned char *from, +unsigned char *to,RSA *rsa, +int padding)) +{ +if (meth) + { + meth->rsa_pub_dec = pub_dec; +return 1 ; + } +return 0 ; +} +#endif + +#if !defined(HAVE_RSA_METH_SET_PRIV_ENC ) +/** +* Set the private encoding function of an RSA_METHOD object +* +* @param meth The RSA_METHOD object +* @param priv_enc the private encoding function +* @return 1 on success, 0 on error +*/ +static inline int +RSA_meth_set_priv_enc (RSA_METHOD *meth, +int (*priv_enc) (int flen,const unsigned char *from, +unsigned char *to,RSA *rsa, +int padding)) +{ +if (meth) + { + meth->rsa_priv_enc = priv_enc; +return 1 ; + } +return 0 ; +} +#endif + +#if !defined(HAVE_RSA_METH_SET_PRIV_DEC ) +/** +* Set the private decoding function of an RSA_METHOD object +* +* @param meth The RSA_METHOD object +* @param priv_dec the private decoding function +* @return 1 on success, 0 on error +*/ +static inline int +RSA_meth_set_priv_dec (RSA_METHOD *meth, +int (*priv_dec) (int flen,const unsigned char *from, +unsigned char *to,RSA *rsa, +int padding)) +{ +if (meth) + { + meth->rsa_priv_dec = priv_dec; +return 1 ; + } +return 0 ; +} +#endif + +#if !defined(HAVE_RSA_METH_SET_INIT ) +/** +* Set the init function of an RSA_METHOD object +* +* @param meth The RSA_METHOD object +* @param init the init function +* @return 1 on success, 0 on error +*/ +static inline int +RSA_meth_set_init (RSA_METHOD *meth,int (*init) (RSA *rsa)) +{ +if (meth) + { + meth->init = init; +return 1 ; + } +return 0 ; +} +#endif + +#if !defined(HAVE_RSA_METH_SET_FINISH ) +/** +* Set the finish function of an RSA_METHOD object +* +* @param meth The RSA_METHOD object +* @param finish the finish function +* @return 1 on success, 0 on error +*/ +static inline int +RSA_meth_set_finish (RSA_METHOD *meth,int (*finish) (RSA *rsa)) +{ +if (meth) + { + meth->finish = finish; +return 1 ; + } +return 0 ; +} +#endif + +#if !defined(HAVE_RSA_METH_SET0_APP_DATA ) +/** +* Set the application data of an RSA_METHOD object +* +* @param meth The RSA_METHOD object +* @param app_data Application data +* @return 1 on success, 0 on error +*/ +static inline int +RSA_meth_set0_app_data (RSA_METHOD *meth,void *app_data) +{ +if (meth) + { + meth->app_data = app_data; +return 1 ; + } +return 0 ; +} +#endif +#endif /* OPENSSL_COMPAT_H_ */ src/openvpn/ssl_openssl.c +0
-0src/openvpn/ssl_openssl.c rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, i · line 984
Quoted 8 lines
src/openvpn/ssl_openssl.c +1
-1@@ -978,7 +978,7 @@ rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, istatic int rsa_finish (RSA *rsa) { -free ((void *)rsa->meth); +RSA_meth_free (rsa->meth); rsa->meth =NULL ;return 1 ; }This change still works, but he follow up change in this method in 07/15 causes problems:
static int rsa_finish(RSA *rsa) { - RSA_meth_free(rsa->meth); - rsa->meth = NULL; + RSA_METHOD *meth = (RSA_METHOD *)RSA_get_method(rsa); + RSA_meth_free(meth); + RSA_set_method(rsa, NULL); return 1; }Casting away const on the object returned by
RSA_get_method()is a smell, but it really fails becauseRSA_set_method(rsa, NULL)callsrsa->meth->finish(), which is implemented by this very function. That means thatRSA_meth_free()will perform a double free onmeth->name.
Quoted 4 lines
I briefly looked into a fix, but didn't immediately see a nice solution here. At least the
RSA_set_method(rsa, RSA_get_default_method())doesn't work either, because you'll end up withrsa_finish()andRSA_set_method()calling each other infinitely...
Ouch. I failed to see that as well. Sorry :)
I'll try to find a better solution to this issue as well.
Quoted 28 lines
(Noting this here, because the fix for 07 might cause changes to this patch too.)
Quoted 25 lines
src/openvpn/ssl_openssl.c +10
-10@@ -1053,16 +1053,16 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx,ASSERT (NULL != cert);/* allocate custom RSA method object */ -ALLOC_OBJ_CLEAR (rsa_meth,RSA_METHOD ); - rsa_meth->name ="OpenVPN external private key RSA Method" ; - rsa_meth->rsa_pub_enc = rsa_pub_enc; - rsa_meth->rsa_pub_dec = rsa_pub_dec; - rsa_meth->rsa_priv_enc = rsa_priv_enc; - rsa_meth->rsa_priv_dec = rsa_priv_dec; - rsa_meth->init =NULL ; - rsa_meth->finish = rsa_finish; - rsa_meth->flags =RSA_METHOD_FLAG_NO_CHECK ; - rsa_meth->app_data =NULL ; + rsa_meth =RSA_meth_new ("OpenVPN external private key RSA Method" , +RSA_METHOD_FLAG_NO_CHECK ); +check_malloc_return (rsa_meth); +RSA_meth_set_pub_enc (rsa_meth, rsa_pub_enc); +RSA_meth_set_pub_dec (rsa_meth, rsa_pub_dec); +RSA_meth_set_priv_enc (rsa_meth, rsa_priv_enc); +RSA_meth_set_priv_dec (rsa_meth, rsa_priv_dec); +RSA_meth_set_init (rsa_meth,NULL ); +RSA_meth_set_finish (rsa_meth, rsa_finish); +RSA_meth_set0_app_data (rsa_meth,NULL );
Quoted 6 lines
src/openvpn/ssl_openssl.c tls_ctx_use_external_private_key(struct tls_root_ctx *ctx, · line 1068
Quoted 3 lines
src/openvpn/ssl_openssl.c +0
-0/* allocate RSA object */ rsa =RSA_new ();-Steffan
Best regards,
-- Emmanuel Deloget
RFC PATCH 5/15 OpenSSL: don't use direct access to the internal of X509
In reply to [email protected]...From: Emmanuel Deloget <[email protected]...>
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including X509. We have to use the defined functions to do so.
In x509_verify_ns_cert_type() in particular, this means that we cannot directly check for the extended flags to find whether the certificate should be used as a client or as a server certificate. We need to leverage the X509_check_purpose() API yet this API is far stricter than the currently implemented check. So far, I have not been able to find a situation where this stricter test fails (although I must admit that I haven't tested that very well).
Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
--- configure.ac | 1 + src/openvpn/openssl_compat.h | 15 +++++++++++++++ src/openvpn/ssl_openssl.c | 3 ++- src/openvpn/ssl_verify_openssl.c | 28 +++++++++++++++++++--------- 4 files changed, 37 insertions(+), 10 deletions(-)
configure.ac +1 -0
@@ -902,6 +902,7 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then [ \ SSL_CTX_get_default_passwd_cb \ SSL_CTX_get_default_passwd_cb_userdata \ + X509_get0_pubkey \ X509_STORE_get0_objects \ X509_OBJECT_free \ X509_OBJECT_get_type \
src/openvpn/openssl_compat.h +15 -0
@@ -74,6 +74,21 @@ SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx) }#endif +#if !defined(HAVE_X509_GET0_PUBKEY ) +/** +* Get the public key from a X509 certificate +* +* @param x X509 certificate +* @return The certificate public key +*/ +static inline EVP_PKEY * +X509_get0_pubkey (const X509 *x) +{ +return (x && x->cert_info && x->cert_info->key) ? + x->cert_info->key->pkey :NULL ; +} +#endif +#if !defined(HAVE_X509_STORE_GET0_OBJECTS )/** * Fetch the X509 object stack from the X509 store
src/openvpn/ssl_openssl.c +2 -1
@@ -1073,7 +1073,8 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx, }/* get the public key */ -ASSERT (cert->cert_info->key->pkey);/* NULL before SSL_CTX_use_certificate() is called */ +EVP_PKEY *pkey =X509_get0_pubkey (cert); +ASSERT (pkey);/* NULL before SSL_CTX_use_certificate() is called */ pub_rsa = cert->cert_info->key->pkey->pkey.rsa;/* initialize RSA object */
src/openvpn/ssl_verify_openssl.c +19 -9
@@ -285,18 +285,20 @@ backend_x509_get_serial_hex(openvpn_x509_cert_t *cert, struct gc_arena *gc)struct buffer x509_get_sha1_fingerprint (X509 *cert,struct gc_arena *gc) { -struct buffer hash =alloc_buf_gc (sizeof (cert->sha1_hash), gc); -memcpy (BPTR (&hash), cert->sha1_hash,sizeof (cert->sha1_hash)); -ASSERT (buf_inc_len (&hash,sizeof (cert->sha1_hash))); +const EVP_MD *sha1 =EVP_sha1 (); +struct buffer hash =alloc_buf_gc (EVP_MD_size (sha1), gc); +X509_digest (cert,EVP_sha1 (),BPTR (&hash),NULL ); +ASSERT (buf_inc_len (&hash,EVP_MD_size (sha1)));return hash; }struct buffer x509_get_sha256_fingerprint (X509 *cert,struct gc_arena *gc) { -struct buffer hash =alloc_buf_gc ((EVP_sha256 ())->md_size, gc); +const EVP_MD *sha256 =EVP_sha256 (); +struct buffer hash =alloc_buf_gc (EVP_MD_size (sha256), gc);X509_digest (cert,EVP_sha256 (),BPTR (&hash),NULL ); -ASSERT (buf_inc_len (&hash, (EVP_sha256 ())->md_size)); +ASSERT (buf_inc_len (&hash,EVP_MD_size (sha256)));return hash; }
@@ -573,13 +575,21 @@ x509_verify_ns_cert_type(const openvpn_x509_cert_t *peer_cert, const int usage) }if (usage ==NS_CERT_CHECK_CLIENT ) { -return ((peer_cert->ex_flags &EXFLAG_NSCERT ) - && (peer_cert->ex_nscert &NS_SSL_CLIENT )) ?SUCCESS :FAILURE ; +/* +* Unfortunately, X509_check_purpose() does some wierd thing that +* prevent it to take a const argument +*/ +return X509_check_purpose ((X509 *)peer_cert,X509_PURPOSE_SSL_CLIENT ,0 ) ? +SUCCESS :FAILURE ; }if (usage ==NS_CERT_CHECK_SERVER ) { -return ((peer_cert->ex_flags &EXFLAG_NSCERT ) - && (peer_cert->ex_nscert &NS_SSL_SERVER )) ?SUCCESS :FAILURE ; +/* +* Unfortunately, X509_check_purpose() does some wierd thing that +* prevent it to take a const argument +*/ +return X509_check_purpose ((X509 *)peer_cert,X509_PURPOSE_SSL_SERVER ,0 ) ? +SUCCESS :FAILURE ; }return FAILURE ;
Signature · 1 line
2.7.4
Re: [Openvpn-devel] [RFC PATCH v1 05/15] OpenSSL: don't use direct access to the internal of X509
Hi,
Quoted 6 lines · On 17-02-17 23:00, [email protected]... wrote:
From: Emmanuel Deloget <[email protected]...>
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including X509. We have to use the defined functions to do so.
Quoted 7 lines
In
x509_verify_ns_cert_type()in particular, this means that we cannot directly check for the extended flags to find whether the certificate should be used as a client or as a server certificate. We need to leverage theX509_check_purpose()API yet this API is far stricter than the currently implemented check. So far, I have not been able to find a situation where this stricter test fails (although I must admit that I haven't tested that very well).
The nsCertType x509 extension is very old, and replaced by keyUsage and extendedKeyUsage (supported by OpenVPN via --remote-cert-tls or --remote-cert-ku and --remote-cert-eku).
Changing this to the stricter API without warning will probably break some people's setups with certs that do have nsCertType set, but not keyUsage and/or extendedKeyUsage, while leaving them guessing why.
So, what I propose instead is:
* remove all the nsCertType code (except the option in add_option())
* update the help strings and man page to indicate that --ns-cert-type
is no longer supported and --remote-cert-tls should be used instead
* in add_option(), if the option is enabled in a config file, act as if
--remote-cert-tls was specified correspondingly, and print a clear warning that --ns-cert-type is no longer supported and stricter checks are enabled instead.
Quoted 110 lines
Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
Signed-off-by Emmanuel Deloget <[email protected]...>--- configure.ac | 1 + src/openvpn/openssl_compat.h | 15 +++++++++++++++ src/openvpn/ssl_openssl.c | 3 ++- src/openvpn/ssl_verify_openssl.c | 28 +++++++++++++++++++--------- 4 files changed, 37 insertions(+), 10 deletions(-)configure.ac +1
-0@@ -902,6 +902,7 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then [ \ SSL_CTX_get_default_passwd_cb \ SSL_CTX_get_default_passwd_cb_userdata \ + X509_get0_pubkey \ X509_STORE_get0_objects \ X509_OBJECT_free \ X509_OBJECT_get_type \src/openvpn/openssl_compat.h +15
-0@@ -74,6 +74,21 @@ SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx) }#endif +#if !defined(HAVE_X509_GET0_PUBKEY ) +/** +* Get the public key from a X509 certificate +* +* @param x X509 certificate +* @return The certificate public key +*/ +static inline EVP_PKEY * +X509_get0_pubkey (const X509 *x) +{ +return (x && x->cert_info && x->cert_info->key) ? + x->cert_info->key->pkey :NULL ; +} +#endif +#if !defined(HAVE_X509_STORE_GET0_OBJECTS )/** * Fetch the X509 object stack from the X509 store src/openvpn/ssl_openssl.c +2
-1@@ -1073,7 +1073,8 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx, }/* get the public key */ -ASSERT (cert->cert_info->key->pkey);/* NULL before SSL_CTX_use_certificate() is called */ +EVP_PKEY *pkey =X509_get0_pubkey (cert); +ASSERT (pkey);/* NULL before SSL_CTX_use_certificate() is called */ pub_rsa = cert->cert_info->key->pkey->pkey.rsa;/* initialize RSA object */ src/openvpn/ssl_verify_openssl.c +13
-8@@ -285,18 +285,20 @@ backend_x509_get_serial_hex(openvpn_x509_cert_t *cert, struct gc_arena *gc)struct buffer x509_get_sha1_fingerprint (X509 *cert,struct gc_arena *gc) { -struct buffer hash =alloc_buf_gc (sizeof (cert->sha1_hash), gc); -memcpy (BPTR (&hash), cert->sha1_hash,sizeof (cert->sha1_hash)); -ASSERT (buf_inc_len (&hash,sizeof (cert->sha1_hash))); +const EVP_MD *sha1 =EVP_sha1 (); +struct buffer hash =alloc_buf_gc (EVP_MD_size (sha1), gc); +X509_digest (cert,EVP_sha1 (),BPTR (&hash),NULL ); +ASSERT (buf_inc_len (&hash,EVP_MD_size (sha1)));return hash; }struct buffer x509_get_sha256_fingerprint (X509 *cert,struct gc_arena *gc) { -struct buffer hash =alloc_buf_gc ((EVP_sha256 ())->md_size, gc); +const EVP_MD *sha256 =EVP_sha256 (); +struct buffer hash =alloc_buf_gc (EVP_MD_size (sha256), gc);X509_digest (cert,EVP_sha256 (),BPTR (&hash),NULL ); -ASSERT (buf_inc_len (&hash, (EVP_sha256 ())->md_size)); +ASSERT (buf_inc_len (&hash,EVP_MD_size (sha256)));return hash; }@@ -573,13 +575,21 @@ x509_verify_ns_cert_type(const openvpn_x509_cert_t *peer_cert, const int usage) }if (usage ==NS_CERT_CHECK_CLIENT ) { -return ((peer_cert->ex_flags &EXFLAG_NSCERT ) - && (peer_cert->ex_nscert &NS_SSL_CLIENT )) ?SUCCESS :FAILURE ; +/* +* Unfortunately, X509_check_purpose() does some wierd thing that +* prevent it to take a const argument +*/ +return X509_check_purpose ((X509 *)peer_cert,X509_PURPOSE_SSL_CLIENT ,0 ) ? +SUCCESS :FAILURE ; }if (usage ==NS_CERT_CHECK_SERVER ) { - return ((peer_cert->ex_flags & EXFLAG_NSCERT)
src/openvpn/ssl_verify_openssl.c x509_verify_ns_cert_type(const openvpn_x509_cert_t *peer_cert, const int usage) · line 595
Quoted 10 lines
src/openvpn/ssl_verify_openssl.c +6
-1- && (peer_cert->ex_nscert & NS_SSL_SERVER)) ? SUCCESS : FAILURE; +/* +* Unfortunately, X509_check_purpose() does some wierd thing that +* prevent it to take a const argument +*/ +return X509_check_purpose ((X509 *)peer_cert,X509_PURPOSE_SSL_SERVER ,0 ) ? +SUCCESS :FAILURE ; }return FAILURE ;
If we are to use X509_check_purpose() (see my comments above), we should not cast away const here, but rather remove the const qualified from the peer_cert argument. Casting away const is bad, in particular if a comment on the function states that it really can't take a const argument because it changes the object.
-Steffan
Re: [Openvpn-devel] [RFC PATCH v1 05/15] OpenSSL: don't use direct access to the internal of X509
Hi,
Quoted 8 lines · Steffan Karger
So, what I propose instead is:
* remove all the nsCertType code (except the option inadd_option())
* update the help strings and man page to indicate that --ns-cert-type
is no longer supported and --remote-cert-tls should be used instead
* inadd_option(), if the option is enabled in a config file, act as if
--remote-cert-tls was specified correspondingly, and print a clear warning that --ns-cert-type is no longer supported and stricter checks are enabled instead.
Mmmmh. Is there a way to get the old behaviour with OpenSSL 1.1?
We decided that we do want 1.1 compatibility in release/2.4, but what you propose might break people's working config when upgrading from 2.4.1 to 2.4.2 - bad enough if we make mistakes, but if there is an alternative to consciously changing cert validation behaviour in the middle of a release train, we should look again...
gert
Signature · 4 lines
USENET is *not* the non-clickable part of WWW!
//www.muc.de/~gert/
Gert Doering - Munich, Germany [email protected]...
fax: +49-89-35655025 [email protected]...Re: [Openvpn-devel] [RFC PATCH v1 05/15] OpenSSL: don't use direct access to the internal of X509
Hi,
Quoted 10 lines · Gert Doering
Quoted 8 lines · Steffan Karger
So, what I propose instead is:
* remove all the nsCertType code (except the option inadd_option())
* update the help strings and man page to indicate that --ns-cert-type
is no longer supported and --remote-cert-tls should be used instead
* inadd_option(), if the option is enabled in a config file, act as if
--remote-cert-tls was specified correspondingly, and print a clear warning that --ns-cert-type is no longer supported and stricter checks are enabled instead.
Quoted 7 lines
Mmmmh. Is there a way to get the old behaviour with OpenSSL 1.1?
We decided that we do want 1.1 compatibility in release/2.4, but what you propose might break people's working config when upgrading from 2.4.1 to 2.4.2 - bad enough if we make mistakes, but if there is an alternative to consciously changing cert validation behaviour in the middle of a release train, we should look again...
So I looked again, and there really seems to be no way to get the old behaviour with OpenSSL 1.1. However, the exact behaviour of X509_check_purpose() is not as strict as I initially thought. The current patch basically adds the following checks:
* if the cert has key usage set, it must be correct
* if the cert has extended key usage set, it must be correct
* if the cert has the CA flag set, it must be done correctly
These are fairly low-risk. I'd expect quite some issues if we would reject certs *without* (extended) key usage set, but if (e)ku is set, this will most likely be done correctly. Or in other words, we might reject weird certificates, but not proper certificates.
All in all, I think the original patch (after fixing const correctness) is fine.
As a last resort, we could consider keeping the old code inside #if OSSL_VER < 1.1.0 in release/2.4, but that might just create more confusion...
-Steffan
Re: [Openvpn-devel] [RFC PATCH v1 05/15] OpenSSL: don't use direct access to the internal of X509
Hello,
Quoted 21 lines · Steffan Karger
Hi,
Quoted 10 lines · Gert Doering
Quoted 8 lines · Steffan Karger
So, what I propose instead is:
* remove all the nsCertType code (except the option inadd_option())
* update the help strings and man page to indicate that --ns-cert-type
is no longer supported and --remote-cert-tls should be used instead
* inadd_option(), if the option is enabled in a config file, act as if
--remote-cert-tls was specified correspondingly, and print a clear warning that --ns-cert-type is no longer supported and stricter checks are enabled instead.Quoted 7 lines
Mmmmh. Is there a way to get the old behaviour with OpenSSL 1.1?
We decided that we do want 1.1 compatibility in release/2.4, but what you propose might break people's working config when upgrading from 2.4.1 to 2.4.2 - bad enough if we make mistakes, but if there is an alternative to consciously changing cert validation behaviour in the middle of a release train, we should look again...
Quoted 7 lines
So I looked again, and there really seems to be no way to get the old behaviour with OpenSSL 1.1. However, the exact behaviour of
X509_check_purpose()is not as strict as I initially thought. The current patch basically adds the following checks:
* if the cert has key usage set, it must be correct
* if the cert has extended key usage set, it must be correct
* if the cert has the CA flag set, it must be done correctly
When I coded this part, I searched for a long time before resorting to using this function. It's true that the library does more check, yet I didn't find any way to not do them, as the necessary members are not available through getters.
However, my understanding is that OpenSSL does a full, correct check, and that certificates that does not pass this check are probably not correct - or at least, they hide some weird issues that could make them a bit dangerous to use. Of course, I might be wrong. The certificates I tested were valid w.r.t. this new code and I'm now sure how I can generate certificates that do not pass.
Quoted 4 lines
These are fairly low-risk. I'd expect quite some issues if we would reject certs *without* (extended) key usage set, but if (e)ku is set, this will most likely be done correctly. Or in other words, we might reject weird certificates, but not proper certificates.
Yet, rejecting certificates might pose problems in the organisations that use them, and they should be warned by (at least) and intermediate release that their certificates going to be rejected. So, after a bit of thinking I would do :
1/ check the certificate with X209_check_purpose()
2/ on failure, for OpenSSL < 1.1.0, warn the user that the certificates are probably not fully correct, and do the old check. If it pass, continue
Quoted 6 lines
All in all, I think the original patch (after fixing const correctness) is fine.
As a last resort, we could consider keeping the old code inside #if
OSSL_VER< 1.1.0 in release/2.4, but that might just create more confusion...
Unfortunately, I am overbooked right now and I'm not sure I'll be able to do this fast (say, in less than 2 weeks). I'd be grateful of someone else does it.
Quoted 1 line
-Steffan
Best regards,
-- Emmanuel Deloget
Re: [Openvpn-devel] [RFC PATCH v1 05/15] OpenSSL: don't use direct access to the internal of X509
In reply to Steffan KargerQuoted 3 lines · Steffan Karger
As a last resort, we could consider keeping the old code inside #if
OSSL_VER< 1.1.0 in release/2.4, but that might just create more confusion...
Just a very quick thought here ... I do dislike different behaviours depending on which OpenSSL version being used. But given that this feature is already deprecated and even removed in OpenSSL-1.1, I think that gives us some options.
I agree with Gert that breaking --ns-cert-type isn't good at all. However, consider when people upgrade from OpenSSL v1.0 to v1.1 - that is most commonly when there is major distro update. It is not something which happens "mid-term", as OpenSSL is quite commonly used by lots of base system packages these days.
Regardless of OpenSSL version, I agree to loudly deprecate --ns-cert-type, through documentation, --help and log files.
But I think we need to carry the existing behaviour for --ns-cert-type when built against OpenSSL v1.0. And we can solve through some compatibility wrapper when built against OpenSSL v1.1 - with even louder warnings in the logs that this may break apart.
The reason I say this, is that Fedora users are quite unhappy that --tls-remote disappeared in v2.4.0 *despite* a more recent NetworkManager-OpenVPN plug-in actually making it easy to switch to --verify-x509-name. But IIRC, this wasn't backported to all older and still valid Fedora releases, so that caused additional pain for the
users. And don't get me started with the attempt of temporarily build
against mbed TLS instead of OpenSSL in Fedora Rawhide (which will become Fedora 26), as that broke lots of configurations with CA certificates using RSA 1024 bit keys. All this results in very little OpenVPN 2.4 adaptation among many Fedora users.
I can barely imagine what happens if we break --ns-cert-type on top of that ... Just that the behaviour might change for a minority of users in when Fedora 26 hits the streets, with OpenSSL v1.1, might hit us bad again. But at least with OpenSSL v1.1, many users knows that things will be somewhat different too. And we can actually point at OpenSSL and explain why it broke, which is not something we could do with the --tls-remote option.
Just my way too many cents ..... :)
Signature · 4 lines
kind regards, David Sommerseth OpenVPN Technologies, Inc
Re: [Openvpn-devel] [RFC PATCH v1 05/15] OpenSSL: don't use direct access to the internal of X509
Hi everyone,
I got some time to try to fix all that stuff.
First,
Quoted 5 lines · David Sommerseth
Quoted 3 lines · Steffan Karger
As a last resort, we could consider keeping the old code inside #if
OSSL_VER< 1.1.0 in release/2.4, but that might just create more confusion...
I think I found a solution -- see later in the email.
I had a closer look to the corresponding code to see what are the differences between the old check and the new one -- and indeed, the discrepancies might only happen if the tested certificate is kind-of-weird. For exemple, a client certificate:
* has the client bit set
* has no key, or has a key but the key usage is neither for signature nor for key agreement
* is not used to auth a client
If a user creates a Frankenstein certificate that look like this, it might be a good idea to warn him that such certificate is very likely to be refused in the near future (one can have a similar reasonning about server certificates).
Quoted 12 lines
Just a very quick thought here ... I do dislike different behaviours depending on which OpenSSL version being used. But given that this feature is already deprecated and even removed in OpenSSL-1.1, I think that gives us some options.
I agree with Gert that breaking --ns-cert-type isn't good at all. However, consider when people upgrade from OpenSSL v1.0 to v1.1 - that is most commonly when there is major distro update. It is not something which happens "mid-term", as OpenSSL is quite commonly used by lots of base system packages these days.
Quoted 8 lines
Regardless of OpenSSL version, I agree to loudly deprecate --ns-cert-type, through documentation, --help and log files.
But I think we need to carry the existing behaviour for --ns-cert-type when built against OpenSSL v1.0. And we can solve through some compatibility wrapper when built against OpenSSL v1.1 - with even louder warnings in the logs that this may break apart.
Fortunately, I think I found a solution that would help when using OpenSSL 1.1. Idealy, this should be a call to X509_check_purpose(.., X509_PURPOSE_SSL_*_WEAK, ...) but I don't think the OpenSSL developers will accept such a change :)
It might be possible to use the X509_get_ext_d2i() call like this:
void *ns = X509_get_ext_d2i(x, NID_netscape_cert_type,
NULL, NULL);
In this case, the obtained ns object contains the data we're interested in:
* if it exists, then EXFLAG_NSCERT is set
* if not null, ns is of type ASN1_BIT_STRING, and this type is not opaque (yep, sir).
So the code would look like:
ASN1_BIT_STRING *ns;result_t result = FAILURE;
ns = X509_get_ext_d2i(x, NID_netscape_cert_type, NULL, NULL); if (ns)
{
if (ns->length > 0)
{
int flags = ns->data[0];
if (flags & NS_SSL_CLIENT)
{
result = SUCCESS;
}
}
ASN1_BIT_STRING_free(ns);
}For the record, it's the code that is used within function x509v3_cache_extensions() which builds the X509 flags we are using so I'm failry confident it's the right thing to do (but it's a bit convoluted and I don't like it much).
Good news: the same code should work with nearly all the previous versions of OpenSSL.
Quoted 9 lines
<snip>
--
kind regards,David Sommerseth
OpenVPN Technologies, Inc
I'll post my new patches as soon as I get over every issues that have been talked on the ML (is that even a valid sentence?)
Best regards,
-- Emmanuel Deloget
Re: [Openvpn-devel] [RFC PATCH v1 05/15] OpenSSL: don't use direct access to the internal of X509
Hi,
I'm not sure why but it seems this mail (that I send yesterday) never found its way to the ML. So I re-send it.
Sorry for the inconvenience.
BR,
-- Emmanuel Deloget
Quoted 124 lines · Emmanuel Deloget
Hi everyone,
I got some time to try to fix all that stuff.
First,
Quoted 5 lines · David Sommerseth
Quoted 3 lines · Steffan Karger
As a last resort, we could consider keeping the old code inside #if
OSSL_VER< 1.1.0 in release/2.4, but that might just create more confusion...I think I found a solution -- see later in the email.
I had a closer look to the corresponding code to see what are the differences between the old check and the new one -- and indeed, the discrepancies might only happen if the tested certificate is kind-of-weird. For exemple, a client certificate:
* has the client bit set
* has no key, or has a key but the key usage is neither for signature nor for key agreement
* is not used to auth a clientIf a user creates a Frankenstein certificate that look like this, it might be a good idea to warn him that such certificate is very likely to be refused in the near future (one can have a similar reasonning about server certificates).
Quoted 12 lines
Just a very quick thought here ... I do dislike different behaviours depending on which OpenSSL version being used. But given that this feature is already deprecated and even removed in OpenSSL-1.1, I think that gives us some options.
I agree with Gert that breaking --ns-cert-type isn't good at all. However, consider when people upgrade from OpenSSL v1.0 to v1.1 - that is most commonly when there is major distro update. It is not something which happens "mid-term", as OpenSSL is quite commonly used by lots of base system packages these days.
Quoted 8 lines
Regardless of OpenSSL version, I agree to loudly deprecate --ns-cert-type, through documentation, --help and log files.
But I think we need to carry the existing behaviour for --ns-cert-type when built against OpenSSL v1.0. And we can solve through some compatibility wrapper when built against OpenSSL v1.1 - with even louder warnings in the logs that this may break apart.
Fortunately, I think I found a solution that would help when using OpenSSL 1.1. Idealy, this should be a call to
X509_check_purpose(.., X509_PURPOSE_SSL_*_WEAK, ...) but I don't think the OpenSSL developers will accept such a change :)It might be possible to use the
X509_get_ext_d2i()call like this:void *ns = X509_get_ext_d2i(x,
NID_netscape_cert_type,NULL, NULL);In this case, the obtained ns object contains the data we're interested in:
* if it exists, then
EXFLAG_NSCERTis set
* if not null, ns is of typeASN1_BIT_STRING, and this type is not opaque (yep, sir).So the code would look like:
ASN1_BIT_STRING *ns;
result_tresult = FAILURE;
ns =X509_get_ext_d2i(x, NID_netscape_cert_type, NULL, NULL); if (ns){ if (ns->length > 0) { int flags = ns->data[0]; if (flags & NS_SSL_CLIENT) { result = SUCCESS; } } ASN1_BIT_STRING_free(ns); }For the record, it's the code that is used within function
x509v3_cache_extensions()which builds the X509 flags we are using so I'm failry confident it's the right thing to do (but it's a bit convoluted and I don't like it much).Good news: the same code should work with nearly all the previous versions of OpenSSL.
Quoted 9 lines
<snip>
--
kind regards,David Sommerseth
OpenVPN Technologies, IncI'll post my new patches as soon as I get over every issues that have been talked on the ML (is that even a valid sentence?)
Best regards,
-- Emmanuel Deloget
Re: [Openvpn-devel] [RFC PATCH v1 05/15] OpenSSL: don't use direct access to the internal of X509
Hi,
Quoted 4 lines · Emmanuel Deloget
I'm not sure why but it seems this mail (that I send yesterday) never found its way to the ML. So I re-send it.
Sorry for the inconvenience.
According to
https://www.mail-archive.com/[email protected]/msg14307.html
it arrived fine :-)
gert
Signature · 4 lines
USENET is *not* the non-clickable part of WWW!
//www.muc.de/~gert/
Gert Doering - Munich, Germany [email protected]...
fax: +49-89-35655025 [email protected]...Re: [Openvpn-devel] OpenSSL 1.1 patch set - status?
In reply to Emmanuel DelogetHi Emmanuel,
Quoted 3 lines · Emmanuel Deloget
I'll post my new patches as soon as I get over every issues that have been talked on the ML (is that even a valid sentence?)
I'm wondering where this got stuck - are you waiting for us to move forward (like, missing review of parts of the patch set), or are we waiting for you, and you've been busy?
We didn't really follow up on this from our end since the CVEs and 2.4.2 got in the way - but I think now would be a good time to move ahead with this...
thanks,
gert
Signature · 4 lines
USENET is *not* the non-clickable part of WWW!
//www.muc.de/~gert/
Gert Doering - Munich, Germany [email protected]...
fax: +49-89-35655025 [email protected]...Re: [Openvpn-devel] OpenSSL 1.1 patch set - status?
Hi Gert,
Quoted 11 lines · Gert Doering
Hi Emmanuel,
Quoted 3 lines · Emmanuel Deloget
I'll post my new patches as soon as I get over every issues that have been talked on the ML (is that even a valid sentence?)
I'm wondering where this got stuck - are you waiting for us to move forward (like, missing review of parts of the patch set), or are we waiting for you, and you've been busy?
Problem is that I'm working in a more-than-full-time manner on way-too-many-other subjects :)
Quoted 3 lines
We didn't really follow up on this from our end since the CVEs and 2.4.2 got in the way - but I think now would be a good time to move ahead with this...
I have a git tree out there that I have not fully tested yet. It compiles OK with OpenSSL 0.9.8, 1.0.0, 1.0.1, 1.0.2 and 1.1.0 but I haven't checked the behavior.
The main difference with the previous version of the patch is the way the certificate purpose is checked.
A) we do a fairly full check of the purpose using X509_check_purpose(). This check is harder that the previous version
B) if that fails, we check for the certificate purpose using a lighter method which is strictly equivalent to what was done before (it uses X509_get_ext_d2i() to fetch the certificate type from within the certificate).
The branch is available for viewing on github at
https://github.com/emmanuel-deloget/openvpn/tree/openssl-1.1-v6.
The followup emails contains the 7 patches which are needed to finish the work.
BR,
-- Emmanuel Deloget
PATCH 1/7 OpenSSL: don't use direct access to the internal of X509
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including X509. We have to use the defined functions to do so.
In x509_verify_ns_cert_type() in particular, this means that we cannot directly check for the extended flags to find whether the certificate should be used as a client or as a server certificate. We need to leverage the X509_check_purpose() API yet this API is far stricter than the currently implemented check. So far, I have not been able to find a situation where this stricter test fails (although I must admit that I haven't tested that very well).
We double-check the certificate purpose using "direct access" to the internal of the certificate object (of course, this is not a real direct access, but we still fetch ASN1 strings within the X509 object and we check the internal value of these strings). This allow us to warn the user if there is a discrepancy between the X509_check_purpose() return value and our internal, less strict check.
Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
--- configure.ac | 1 + src/openvpn/openssl_compat.h | 15 ++++++++++ src/openvpn/ssl_openssl.c | 3 +- src/openvpn/ssl_verify_openssl.c | 64 ++++++++++++++++++++++++++++++++++------ 4 files changed, 73 insertions(+), 10 deletions(-)
configure.ac +1 -0
@@ -922,6 +922,7 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then [ \ SSL_CTX_get_default_passwd_cb \ SSL_CTX_get_default_passwd_cb_userdata \ + X509_get0_pubkey \ X509_STORE_get0_objects \ X509_OBJECT_free \ X509_OBJECT_get_type \
src/openvpn/openssl_compat.h +15 -0
@@ -74,6 +74,21 @@ SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx) }#endif +#if !defined(HAVE_X509_GET0_PUBKEY ) +/** +* Get the public key from a X509 certificate +* +* @param x X509 certificate +* @return The certificate public key +*/ +static inline EVP_PKEY * +X509_get0_pubkey (const X509 *x) +{ +return (x && x->cert_info && x->cert_info->key) ? + x->cert_info->key->pkey :NULL ; +} +#endif +#if !defined(HAVE_X509_STORE_GET0_OBJECTS )/** * Fetch the X509 object stack from the X509 store
src/openvpn/ssl_openssl.c +2 -1
@@ -1070,7 +1070,8 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx, }/* get the public key */ -ASSERT (cert->cert_info->key->pkey);/* NULL before SSL_CTX_use_certificate() is called */ +EVP_PKEY *pkey =X509_get0_pubkey (cert); +ASSERT (pkey);/* NULL before SSL_CTX_use_certificate() is called */ pub_rsa = cert->cert_info->key->pkey->pkey.rsa;/* initialize RSA object */
src/openvpn/ssl_verify_openssl.c +55 -9
86 lines not on this page · raw message
Signature · 1 line
2.11.0
PATCH 2/7 OpenSSL: don't use direct access to the internal of EVP_PKEY
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including EVP_PKEY. We have to use the defined functions to do so.
Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
--- configure.ac | 3 +++ src/openvpn/openssl_compat.h | 42 ++++++++++++++++++++++++++++++++++++++++++ src/openvpn/ssl_openssl.c | 6 +++--- 3 files changed, 48 insertions(+), 3 deletions(-)
configure.ac +3 -0
@@ -926,6 +926,9 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then X509_STORE_get0_objects \ X509_OBJECT_free \ X509_OBJECT_get_type \ + EVP_PKEY_id \ + EVP_PKEY_get0_RSA \ + EVP_PKEY_get0_DSA \ RSA_meth_new \ RSA_meth_free \ RSA_meth_set_pub_enc \
src/openvpn/openssl_compat.h +42 -0
48 lines not on this page · raw message
src/openvpn/ssl_openssl.c +3 -3
@@ -1072,7 +1072,7 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx,/* get the public key */ EVP_PKEY *pkey =X509_get0_pubkey (cert);ASSERT (pkey);/* NULL before SSL_CTX_use_certificate() is called */ - pub_rsa = cert->cert_info->key->pkey->pkey.rsa; + pub_rsa =EVP_PKEY_get0_RSA (pkey);/* initialize RSA object */ rsa->n =BN_dup (pub_rsa->n);
@@ -1677,13 +1677,13 @@ print_details(struct key_state_ssl *ks_ssl, const char *prefix)EVP_PKEY *pkey =X509_get_pubkey (cert);if (pkey !=NULL ) { -if (pkey->type ==EVP_PKEY_RSA && pkey->pkey.rsa !=NULL +if (EVP_PKEY_id (pkey) ==EVP_PKEY_RSA &&EVP_PKEY_get0_RSA (pkey) !=NULL && pkey->pkey.rsa->n !=NULL ) {openvpn_snprintf (s2,sizeof (s2),", %d bit RSA" ,BN_num_bits (pkey->pkey.rsa->n)); } -else if (pkey->type ==EVP_PKEY_DSA && pkey->pkey.dsa !=NULL +else if (EVP_PKEY_id (pkey) ==EVP_PKEY_DSA &&EVP_PKEY_get0_DSA (pkey) !=NULL && pkey->pkey.dsa->p !=NULL ) { openvpn_snprintf(s2, sizeof(s2), ", %d bit DSA",
Signature · 1 line
2.11.0
Re: [Openvpn-devel] [PATCH 2/7] OpenSSL: don't use direct access to the internal of EVP_PKEY
Hi,
Quoted 101 lines · Emmanuel Deloget
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including
EVP_PKEY. We have to use the defined functions to do so.Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
Signed-off-by Emmanuel Deloget <[email protected]...>--- configure.ac | 3 +++ src/openvpn/openssl_compat.h | 42 ++++++++++++++++++++++++++++++++++++++++++ src/openvpn/ssl_openssl.c | 6 +++--- 3 files changed, 48 insertions(+), 3 deletions(-)configure.ac +3
-0@@ -926,6 +926,9 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then X509_STORE_get0_objects \ X509_OBJECT_free \ X509_OBJECT_get_type \ + EVP_PKEY_id \ + EVP_PKEY_get0_RSA \ + EVP_PKEY_get0_DSA \ RSA_meth_new \ RSA_meth_free \ RSA_meth_set_pub_enc \src/openvpn/openssl_compat.h +42
-0@@ -134,6 +134,48 @@ X509_OBJECT_get_type(const X509_OBJECT *obj) }#endif +#if !defined(HAVE_EVP_PKEY_GET0_RSA ) +/** +* Get the RSA object of a public key +* +* @param pkey Public key object +* @return The underlying RSA object +*/ +static inline RSA * +EVP_PKEY_get0_RSA (EVP_PKEY *pkey) +{ +return pkey ? pkey->pkey.rsa :NULL ; +} +#endif + +#if !defined(HAVE_EVP_PKEY_ID ) +/** +* Get the PKEY type +* +* @param pkey Public key object +* @return The key type +*/ +static inline int +EVP_PKEY_id (const EVP_PKEY *pkey) +{ +return pkey ? pkey->type :EVP_PKEY_NONE ; +} +#endif + +#if !defined(HAVE_EVP_PKEY_GET0_DSA ) +/** +* Get the DSA object of a public key +* +* @param pkey Public key object +* @return The underlying DSA object +*/ +static inline DSA * +EVP_PKEY_get0_DSA (EVP_PKEY *pkey) +{ +return pkey ? pkey->pkey.dsa :NULL ; +} +#endif +#if !defined(HAVE_RSA_METH_NEW )/** * Allocate a new RSA method object src/openvpn/ssl_openssl.c +2
-2@@ -1072,7 +1072,7 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx,/* get the public key */ EVP_PKEY *pkey =X509_get0_pubkey (cert);ASSERT (pkey);/* NULL before SSL_CTX_use_certificate() is called */ - pub_rsa = cert->cert_info->key->pkey->pkey.rsa; + pub_rsa =EVP_PKEY_get0_RSA (pkey);/* initialize RSA object */ rsa->n =BN_dup (pub_rsa->n);@@ -1677,13 +1677,13 @@ print_details(struct key_state_ssl *ks_ssl, const char *prefix)EVP_PKEY *pkey =X509_get_pubkey (cert);if (pkey !=NULL ) { - if (pkey->type == EVP_PKEY_RSA && pkey->pkey.rsa != NULL + if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA && EVP_PKEY_get0_RSA(pkey) != NULL
src/openvpn/ssl_openssl.c print_details(struct key_state_ssl *ks_ssl, const char *prefix) · line 1689
Quoted 10 lines
src/openvpn/ssl_openssl.c +1
-1&& pkey->pkey.rsa->n != NULL) {openvpn_snprintf (s2,sizeof (s2),", %d bit RSA" ,BN_num_bits (pkey->pkey.rsa->n)); } - else if (pkey->type == EVP_PKEY_DSA && pkey->pkey.dsa != NULL + else if (EVP_PKEY_id(pkey) == EVP_PKEY_DSA && EVP_PKEY_get0_DSA(pkey) != NULL && pkey->pkey.dsa->p != NULL) { openvpn_snprintf(s2, sizeof(s2), ", %d bit DSA",
This looks good to me - ACK.
-Steffan
PATCH 3/7 OpenSSL: don't use direct access to the internal of RSA
In reply to Emmanuel DelogetOpenSSL 1.1 does not allow us to directly access the internal of any data type, including RSA. We have to use the defined functions to do so.
Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
--- configure.ac | 3 ++ src/openvpn/openssl_compat.h | 84 ++++++++++++++++++++++++++++++++++++++++++++ src/openvpn/ssl_openssl.c | 24 ++++++++----- 3 files changed, 103 insertions(+), 8 deletions(-)
configure.ac +3 -0
@@ -929,6 +929,9 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then EVP_PKEY_id \ EVP_PKEY_get0_RSA \ EVP_PKEY_get0_DSA \ + RSA_set_flags \ + RSA_get0_key \ + RSA_set0_key \ RSA_meth_new \ RSA_meth_free \ RSA_meth_set_pub_enc \
src/openvpn/openssl_compat.h +84 -0
90 lines not on this page · raw message
src/openvpn/ssl_openssl.c +16 -8
@@ -975,8 +975,8 @@ rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, istatic int rsa_finish (RSA *rsa) { -RSA_meth_free (rsa->meth); - rsa->meth =NULL ; +const RSA_METHOD *meth =RSA_get_method (rsa); +RSA_meth_free ((RSA_METHOD *)meth);return 1 ; }
@@ -1075,8 +1075,11 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx, pub_rsa =EVP_PKEY_get0_RSA (pkey);/* initialize RSA object */ - rsa->n =BN_dup (pub_rsa->n); - rsa->flags |=RSA_FLAG_EXT_PKEY ; +const BIGNUM *n =NULL ; +const BIGNUM *e =NULL ; +RSA_get0_key (pub_rsa, &n, &e,NULL ); +RSA_set0_key (rsa,BN_dup (n),BN_dup (e),NULL ); +RSA_set_flags (rsa,RSA_flags (rsa) |RSA_FLAG_EXT_PKEY );if (!RSA_set_method (rsa, rsa_meth)) { goto err;
@@ -1677,11 +1680,16 @@ print_details(struct key_state_ssl *ks_ssl, const char *prefix)EVP_PKEY *pkey =X509_get_pubkey (cert);if (pkey !=NULL ) { -if (EVP_PKEY_id (pkey) ==EVP_PKEY_RSA &&EVP_PKEY_get0_RSA (pkey) !=NULL - && pkey->pkey.rsa->n !=NULL ) +if (EVP_PKEY_id (pkey) ==EVP_PKEY_RSA &&EVP_PKEY_get0_RSA (pkey) !=NULL ) { -openvpn_snprintf (s2,sizeof (s2),", %d bit RSA" , -BN_num_bits (pkey->pkey.rsa->n)); +RSA *rsa =EVP_PKEY_get0_RSA (pkey); +const BIGNUM *n =NULL ; +RSA_get0_key (rsa, &n,NULL ,NULL ); +if (n !=NULL ) + { +openvpn_snprintf (s2,sizeof (s2),", %d bit RSA" , +BN_num_bits (n)); + } }else if (EVP_PKEY_id (pkey) ==EVP_PKEY_DSA &&EVP_PKEY_get0_DSA (pkey) !=NULL && pkey->pkey.dsa->p !=NULL )
Signature · 1 line
2.11.0
Re: [Openvpn-devel] [PATCH 3/7] OpenSSL: don't use direct access to the internal of RSA
Hi,
Patch looks good in general, but some minor remarks:
Quoted 128 lines · Emmanuel Deloget
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including RSA. We have to use the defined functions to do so.
Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
Signed-off-by Emmanuel Deloget <[email protected]...>--- configure.ac | 3 ++ src/openvpn/openssl_compat.h | 84 ++++++++++++++++++++++++++++++++++++++++++++ src/openvpn/ssl_openssl.c | 24 ++++++++----- 3 files changed, 103 insertions(+), 8 deletions(-)configure.ac +3
-0@@ -929,6 +929,9 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then EVP_PKEY_id \ EVP_PKEY_get0_RSA \ EVP_PKEY_get0_DSA \ + RSA_set_flags \ + RSA_get0_key \ + RSA_set0_key \ RSA_meth_new \ RSA_meth_free \ RSA_meth_set_pub_enc \src/openvpn/openssl_compat.h +84
-0@@ -176,6 +176,90 @@ EVP_PKEY_get0_DSA(EVP_PKEY *pkey) }#endif +#if !defined(HAVE_RSA_SET_FLAGS ) +/** +* Set the RSA flags +* +* @param rsa The RSA object +* @param flags New flags value +*/ +static inline void +RSA_set_flags (RSA *rsa,int flags) +{ +if (rsa) + { + rsa->flags = flags; + } +} +#endif + +#if !defined(HAVE_RSA_GET0_KEY ) +/** +* Get the RSA parameters +* +* @param rsa The RSA object +* @param n The @c n parameter +* @param e The @c e parameter +* @param d The @c d parameter +*/ +static inline void +RSA_get0_key (const RSA *rsa,const BIGNUM **n, +const BIGNUM **e,const BIGNUM **d) +{ +if (n !=NULL ) + { + *n = rsa ? rsa->n :NULL ; + } +if (e !=NULL ) + { + *e = rsa ? rsa->e :NULL ; + } +if (d !=NULL ) + { + *d = rsa ? rsa->d :NULL ; + } +} +#endif + +#if !defined(HAVE_RSA_SET0_KEY ) +/** +* Set the RSA parameters +* +* @param rsa The RSA object +* @param n The @c n parameter +* @param e The @c e parameter +* @param d The @c d parameter +* @return 1 on success, 0 on error +*/ +static inline int +RSA_set0_key (RSA *rsa,BIGNUM *n,BIGNUM *e,BIGNUM *d) +{ +if ((rsa->n ==NULL && n ==NULL ) + || (rsa->e ==NULL && e ==NULL )) + { +return 0 ; + } + +if (n !=NULL ) + { +BN_free (rsa->n); + rsa->n = n; + } +if (e !=NULL ) + { +BN_free (rsa->e); + rsa->e = e; + } +if (d !=NULL ) + { +BN_free (rsa->d); + rsa->d = d; + } + +return 1 ; +} +#endif +#if !defined(HAVE_RSA_METH_NEW )/** * Allocate a new RSA method object src/openvpn/ssl_openssl.c +0
-0
src/openvpn/ssl_openssl.c rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, i · line 979
Quoted 7 lines
src/openvpn/ssl_openssl.c +2
-2@@ -975,8 +975,8 @@ rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, istatic int rsa_finish (RSA *rsa) { -RSA_meth_free (rsa->meth); - rsa->meth =NULL ; +const RSA_METHOD *meth =RSA_get_method (rsa); +RSA_meth_free ((RSA_METHOD *)meth);
Casting away const is safe here, but I'd like to make that a bit more obvious. How about renaming 'rsa_finish()' to something like 'openvpn_extkey_rsa_finish' to make clear that this function is specific for management external key. Also, add a comment to mention that 'meth' was allocated in 'tls_ctx_use_external_private_key()' and is safe to fee here.
Quoted 25 lines
src/openvpn/ssl_openssl.c +6
-4return 1 ; }@@ -1075,8 +1075,11 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx, pub_rsa =EVP_PKEY_get0_RSA (pkey);/* initialize RSA object */ - rsa->n =BN_dup (pub_rsa->n); - rsa->flags |=RSA_FLAG_EXT_PKEY ; +const BIGNUM *n =NULL ; +const BIGNUM *e =NULL ; +RSA_get0_key (pub_rsa, &n, &e,NULL ); +RSA_set0_key (rsa,BN_dup (n),BN_dup (e),NULL ); +RSA_set_flags (rsa,RSA_flags (rsa) |RSA_FLAG_EXT_PKEY );if (!RSA_set_method (rsa, rsa_meth)) { goto err;@@ -1677,11 +1680,16 @@ print_details(struct key_state_ssl *ks_ssl, const char *prefix)EVP_PKEY *pkey =X509_get_pubkey (cert);if (pkey !=NULL ) { -if (EVP_PKEY_id (pkey) ==EVP_PKEY_RSA &&EVP_PKEY_get0_RSA (pkey) !=NULL - && pkey->pkey.rsa->n !=NULL ) +if (EVP_PKEY_id (pkey) ==EVP_PKEY_RSA &&EVP_PKEY_get0_RSA (pkey) !=NULL ) {
src/openvpn/ssl_openssl.c print_details(struct key_state_ssl *ks_ssl, const char *prefix) · line 1692
Quoted 10 lines
src/openvpn/ssl_openssl.c +8
-2-openvpn_snprintf (s2,sizeof (s2),", %d bit RSA" , -BN_num_bits (pkey->pkey.rsa->n)); +RSA *rsa =EVP_PKEY_get0_RSA (pkey); +const BIGNUM *n =NULL ; +RSA_get0_key (rsa, &n,NULL ,NULL ); +if (n !=NULL ) + { +openvpn_snprintf (s2,sizeof (s2),", %d bit RSA" , +BN_num_bits (n)); + }
This would be somewhat nicer to partly implement in an RSA_bits() in openssl_compat.h (mimicing OpenSSL 1.1's RSA_bits()).
-Steffan
PATCH 4/7 OpenSSL: don't use direct access to the internal of DSA
In reply to Emmanuel DelogetOpenSSL 1.1 does not allow us to directly access the internal of any data type, including DSA. We have to use the defined functions to do so.
Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
--- configure.ac | 1 + src/openvpn/openssl_compat.h | 28 ++++++++++++++++++++++++++++ src/openvpn/ssl_openssl.c | 13 +++++++++---- 3 files changed, 38 insertions(+), 4 deletions(-)
configure.ac +1 -0
@@ -932,6 +932,7 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then RSA_set_flags \ RSA_get0_key \ RSA_set0_key \ + DSA_get0_pqg \ RSA_meth_new \ RSA_meth_free \ RSA_meth_set_pub_enc \
src/openvpn/openssl_compat.h +28 -0
@@ -260,6 +260,34 @@ RSA_set0_key(RSA *rsa, BIGNUM *n, BIGNUM *e, BIGNUM *d) }#endif +#if !defined(HAVE_DSA_GET0_PQG ) +/** +* Get the DSA parameters +* +* @param dsa The DSA object +* @param p The @c p parameter +* @param q The @c q parameter +* @param g The @c g parameter +*/ +static inline void +DSA_get0_pqg (const DSA *dsa,const BIGNUM **p, +const BIGNUM **q,const BIGNUM **g) +{ +if (p !=NULL ) + { + *p = dsa ? dsa->p :NULL ; + } +if (q !=NULL ) + { + *q = dsa ? dsa->q :NULL ; + } +if (g !=NULL ) + { + *g = dsa ? dsa->g :NULL ; + } +} +#endif +#if !defined(HAVE_RSA_METH_NEW )/** * Allocate a new RSA method object
src/openvpn/ssl_openssl.c +9 -4
@@ -1691,11 +1691,16 @@ print_details(struct key_state_ssl *ks_ssl, const char *prefix) BN_num_bits(n)); } } -else if (EVP_PKEY_id (pkey) ==EVP_PKEY_DSA &&EVP_PKEY_get0_DSA (pkey) !=NULL - && pkey->pkey.dsa->p !=NULL ) +else if (EVP_PKEY_id (pkey) ==EVP_PKEY_DSA &&EVP_PKEY_get0_DSA (pkey) !=NULL ) { -openvpn_snprintf (s2,sizeof (s2),", %d bit DSA" , -BN_num_bits (pkey->pkey.dsa->p)); +DSA *dsa =EVP_PKEY_get0_DSA (pkey); +const BIGNUM *p =NULL ; +DSA_get0_pqg (dsa, &p,NULL ,NULL ); +if (p !=NULL ) + { +openvpn_snprintf (s2,sizeof (s2),", %d bit DSA" , +BN_num_bits (p)); + } }EVP_PKEY_free (pkey); }
Signature · 1 line
2.11.0
Re: [Openvpn-devel] [PATCH 4/7] OpenSSL: don't use direct access to the internal of DSA
Hi,
Quoted 77 lines · Emmanuel Deloget
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including DSA. We have to use the defined functions to do so.
Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
Signed-off-by Emmanuel Deloget <[email protected]...>--- configure.ac | 1 + src/openvpn/openssl_compat.h | 28 ++++++++++++++++++++++++++++ src/openvpn/ssl_openssl.c | 13 +++++++++---- 3 files changed, 38 insertions(+), 4 deletions(-)configure.ac +1
-0@@ -932,6 +932,7 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then RSA_set_flags \ RSA_get0_key \ RSA_set0_key \ + DSA_get0_pqg \ RSA_meth_new \ RSA_meth_free \ RSA_meth_set_pub_enc \src/openvpn/openssl_compat.h +28
-0@@ -260,6 +260,34 @@ RSA_set0_key(RSA *rsa, BIGNUM *n, BIGNUM *e, BIGNUM *d) }#endif +#if !defined(HAVE_DSA_GET0_PQG ) +/** +* Get the DSA parameters +* +* @param dsa The DSA object +* @param p The @c p parameter +* @param q The @c q parameter +* @param g The @c g parameter +*/ +static inline void +DSA_get0_pqg (const DSA *dsa,const BIGNUM **p, +const BIGNUM **q,const BIGNUM **g) +{ +if (p !=NULL ) + { + *p = dsa ? dsa->p :NULL ; + } +if (q !=NULL ) + { + *q = dsa ? dsa->q :NULL ; + } +if (g !=NULL ) + { + *g = dsa ? dsa->g :NULL ; + } +} +#endif +#if !defined(HAVE_RSA_METH_NEW )/** * Allocate a new RSA method object src/openvpn/ssl_openssl.c +1
-2@@ -1691,11 +1691,16 @@ print_details(struct key_state_ssl *ks_ssl, const char *prefix) BN_num_bits(n)); } } -else if (EVP_PKEY_id (pkey) ==EVP_PKEY_DSA &&EVP_PKEY_get0_DSA (pkey) !=NULL - && pkey->pkey.dsa->p !=NULL ) +else if (EVP_PKEY_id (pkey) ==EVP_PKEY_DSA &&EVP_PKEY_get0_DSA (pkey) !=NULL ) {
src/openvpn/ssl_openssl.c print_details(struct key_state_ssl *ks_ssl, const char *prefix) · line 1703
Quoted 10 lines
src/openvpn/ssl_openssl.c +8
-2-openvpn_snprintf (s2,sizeof (s2),", %d bit DSA" , -BN_num_bits (pkey->pkey.dsa->p)); +DSA *dsa =EVP_PKEY_get0_DSA (pkey); +const BIGNUM *p =NULL ; +DSA_get0_pqg (dsa, &p,NULL ,NULL ); +if (p !=NULL ) + { +openvpn_snprintf (s2,sizeof (s2),", %d bit DSA" , +BN_num_bits (p)); + }
Similar to 3/7: a DSA_bits() in openssl_compat.h is somewhat nicer.
-Steffan
PATCH 5/7 OpenSSL: don't use direct access to the internal of EVP_MD_CTX
In reply to Emmanuel DelogetOpenSSL 1.1 does not allow us to directly access the internal of any data type, including EVP_MD_CTX. We have to use the defined functions to do so.
Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
--- configure.ac | 3 ++ src/openvpn/crypto_backend.h | 14 ++++++++ src/openvpn/crypto_mbedtls.c | 12 +++++++ src/openvpn/crypto_openssl.c | 18 ++++++++-- src/openvpn/httpdigest.c | 78 +++++++++++++++++++++++--------------------- src/openvpn/misc.c | 14 ++++---- src/openvpn/openssl_compat.h | 50 ++++++++++++++++++++++++++++ src/openvpn/openvpn.h | 2 +- src/openvpn/push.c | 11 ++++--- 9 files changed, 150 insertions(+), 52 deletions(-)
configure.ac +3 -0
@@ -920,6 +920,9 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then AC_CHECK_FUNCS( [ \ + EVP_MD_CTX_new \ + EVP_MD_CTX_free \ + EVP_MD_CTX_reset \ SSL_CTX_get_default_passwd_cb \ SSL_CTX_get_default_passwd_cb_userdata \ X509_get0_pubkey \
src/openvpn/crypto_backend.h +14 -0
@@ -508,6 +508,20 @@ int md_kt_size(const md_kt_t *kt);int md_full (const md_kt_t *kt,const uint8_t *src,int src_len,uint8_t *dst);/* +* Allocate a new message digest context +* +* @return a new zeroed MD context +*/ +md_ctx_t *md_ctx_new (void ); + +/* +* Free an existing, non-null message digest context +* +* @param ctx Message digest context +*/ +void md_ctx_free (md_ctx_t *ctx); + +/* * Initialises the given message digest context. * * @param ctx Message digest context
src/openvpn/crypto_mbedtls.c +12 -0
@@ -766,6 +766,18 @@ md_full(const md_kt_t *kt, const uint8_t *src, int src_len, uint8_t *dst)return 0 ==mbedtls_md (kt, src, src_len, dst); } +mbedtls_md_context_t * +md_ctx_new (void ) +{ +mbedtls_md_context_t *ctx; +ALLOC_OBJ_CLEAR (ctx, mbedtls_md_context_t); +return ctx; +} + +void md_ctx_free (mbedtls_md_context_t *ctx) +{ +free (ctx); +}void md_ctx_init (mbedtls_md_context_t *ctx,const mbedtls_md_info_t *kt)
src/openvpn/crypto_openssl.c +15 -3
@@ -42,6 +42,7 @@#include "integer.h" #include "crypto.h" #include "crypto_backend.h" +#include "openssl_compat.h" #include <openssl/des.h> #include <openssl/err.h>
@@ -844,13 +845,24 @@ md_full(const EVP_MD *kt, const uint8_t *src, int src_len, uint8_t *dst)return EVP_Digest (src, src_len, dst, &in_md_len, kt,NULL ); } +EVP_MD_CTX * +md_ctx_new (void ) +{ +EVP_MD_CTX *ctx =EVP_MD_CTX_new (); +check_malloc_return (ctx); +return ctx; +} + +void md_ctx_free (EVP_MD_CTX *ctx) +{ +EVP_MD_CTX_free (ctx); +} +void md_ctx_init (EVP_MD_CTX *ctx,const EVP_MD *kt) {ASSERT (NULL != ctx &&NULL != kt); -CLEAR (*ctx); -EVP_MD_CTX_init (ctx);EVP_DigestInit (ctx, kt); }
@@ -858,7 +870,7 @@ md_ctx_init(EVP_MD_CTX *ctx, const EVP_MD *kt)void md_ctx_cleanup (EVP_MD_CTX *ctx) { -EVP_MD_CTX_cleanup (ctx); +EVP_MD_CTX_reset (ctx); }int
src/openvpn/httpdigest.c +40 -38
107 lines not on this page · raw message
src/openvpn/misc.c +8 -6
@@ -1388,7 +1388,7 @@ get_user_pass_auto_userid(struct user_pass *up, const char *tag)static const uint8_t hashprefix[] ="AUTO_USERID_DIGEST" ;const md_kt_t *md5_kt =md_kt_get ("MD5" ); -md_ctx_t ctx; +md_ctx_t *ctx;CLEAR (*up);buf_set_write (&buf, (uint8_t *)up->username,USER_PASS_LEN );
@@ -1396,11 +1396,13 @@ get_user_pass_auto_userid(struct user_pass *up, const char *tag)if (get_default_gateway_mac_addr (macaddr)) {dmsg (D_AUTO_USERID ,"GUPAU: macaddr=%s" ,format_hex_ex (macaddr,sizeof (macaddr),0 ,1 ,":" , &gc)); -md_ctx_init (&ctx, md5_kt); -md_ctx_update (&ctx, hashprefix,sizeof (hashprefix) -1 ); -md_ctx_update (&ctx, macaddr,sizeof (macaddr)); -md_ctx_final (&ctx, digest); - md_ctx_cleanup(&ctx) + ctx =md_ctx_new (); +md_ctx_init (ctx, md5_kt); +md_ctx_update (ctx, hashprefix,sizeof (hashprefix) -1 ); +md_ctx_update (ctx, macaddr,sizeof (macaddr)); +md_ctx_final (ctx, digest); +md_ctx_cleanup (ctx); +md_ctx_free (ctx);buf_printf (&buf,"%s" ,format_hex_ex (digest,sizeof (digest),0 ,256 ," " , &gc)); }else
src/openvpn/openssl_compat.h +50 -0
56 lines not on this page · raw message
src/openvpn/openvpn.h +1 -1
@@ -473,7 +473,7 @@ struct context_2/* hash of pulled options, so we can compare when options change */ bool pulled_options_digest_init_done; -md_ctx_t pulled_options_state; +md_ctx_t *pulled_options_state;struct sha256_digest pulled_options_digest;struct event_timeout scheduled_exit;
src/openvpn/push.c +7 -4
@@ -724,7 +724,8 @@ process_incoming_push_msg(struct context *c,struct buffer buf_orig = buf;if (!c->c2.pulled_options_digest_init_done) { -md_ctx_init (&c->c2.pulled_options_state,md_kt_get ("SHA256" )); + c->c2.pulled_options_state =md_ctx_new (); +md_ctx_init (c->c2.pulled_options_state,md_kt_get ("SHA256" )); c->c2.pulled_options_digest_init_done = true; }if (!c->c2.did_pre_pull_restore)
@@ -738,14 +739,16 @@ process_incoming_push_msg(struct context *c, option_types_found, c->c2.es)) { -push_update_digest (&c->c2.pulled_options_state, &buf_orig, +push_update_digest (c->c2.pulled_options_state, &buf_orig, &c->options);switch (c->options.push_continuation) {case 0 :case 1 : -md_ctx_final (&c->c2.pulled_options_state, c->c2.pulled_options_digest.digest); -md_ctx_cleanup (&c->c2.pulled_options_state); +md_ctx_final (c->c2.pulled_options_state, c->c2.pulled_options_digest.digest); +md_ctx_cleanup (c->c2.pulled_options_state); +md_ctx_free (c->c2.pulled_options_state); + c->c2.pulled_options_state =NULL ; c->c2.pulled_options_digest_init_done = false; ret =PUSH_MSG_REPLY ;break ;
Signature · 1 line
2.11.0
PATCH 6/7 OpenSSL: don't use direct access to the internal of EVP_CIPHER_CTX
In reply to Emmanuel DelogetOpenSSL 1.1 does not allow us to directly access the internal of any data type, including EVP_CIPHER_CTX. We have to use the defined functions to do so.
Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
--- configure.ac | 2 ++ src/openvpn/crypto.c | 4 ++-- src/openvpn/crypto_backend.h | 14 ++++++++++++++ src/openvpn/crypto_mbedtls.c | 13 +++++++++++++ src/openvpn/crypto_openssl.c | 15 +++++++++++++-- src/openvpn/openssl_compat.h | 28 ++++++++++++++++++++++++++++ 6 files changed, 72 insertions(+), 4 deletions(-)
configure.ac +2 -0
@@ -920,6 +920,8 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then AC_CHECK_FUNCS( [ \ + EVP_CIPHER_CTX_new \ + EVP_CIPHER_CTX_free \ EVP_MD_CTX_new \ EVP_MD_CTX_free \ EVP_MD_CTX_reset \
src/openvpn/crypto.c +2 -2
@@ -830,7 +830,7 @@ init_key_ctx(struct key_ctx *ctx, struct key *key,if (kt->cipher && kt->cipher_length >0 ) { -ALLOC_OBJ (ctx->cipher, cipher_ctx_t); + ctx->cipher =cipher_ctx_new ();cipher_ctx_init (ctx->cipher, key->cipher, kt->cipher_length, kt->cipher, enc);
@@ -879,7 +879,7 @@ free_key_ctx(struct key_ctx *ctx)if (ctx->cipher) {cipher_ctx_cleanup (ctx->cipher); -free (ctx->cipher); +cipher_ctx_free (ctx->cipher); ctx->cipher =NULL ; }if (ctx->hmac)
src/openvpn/crypto_backend.h +14 -0
@@ -301,6 +301,20 @@ bool cipher_kt_mode_aead(const cipher_kt_t *cipher);*/ /** +* Allocate a new cipher context +* +* @return a new cipher context +*/ +cipher_ctx_t *cipher_ctx_new (void ); + +/** +* Free a cipher context +* +* @param ctx Cipher context. +*/ +void cipher_ctx_free (cipher_ctx_t *ctx); + +/** * Initialise a cipher context, based on the given key and key type. * * @param ctx Cipher context. May not be NULL
src/openvpn/crypto_mbedtls.c +13 -0
@@ -509,6 +509,19 @@ cipher_kt_mode_aead(const cipher_kt_t *cipher)* */ +mbedtls_cipher_context_t * +cipher_ctx_new (void ) +{ +mbedtls_cipher_context_t *ctx; +ALLOC_OBJ (ctx, mbedtls_cipher_context_t); +return ctx; +} + +void +cipher_ctx_free (mbedtls_cipher_context_t *ctx) +{ +free (ctx); +} void cipher_ctx_init(mbedtls_cipher_context_t *ctx, uint8_t *key, int key_len,
src/openvpn/crypto_openssl.c +13 -2
@@ -651,6 +651,19 @@ cipher_kt_mode_aead(const cipher_kt_t *cipher)* */ +cipher_ctx_t * +cipher_ctx_new (void ) +{ +EVP_CIPHER_CTX *ctx =EVP_CIPHER_CTX_new (); +check_malloc_return (ctx); +return ctx; +} + +void +cipher_ctx_free (EVP_CIPHER_CTX *ctx) +{ +EVP_CIPHER_CTX_free (ctx); +} void cipher_ctx_init(EVP_CIPHER_CTX *ctx, uint8_t *key, int key_len,
@@ -658,8 +671,6 @@ cipher_ctx_init(EVP_CIPHER_CTX *ctx, uint8_t *key, int key_len, {ASSERT (NULL != kt &&NULL != ctx); -CLEAR (*ctx); -EVP_CIPHER_CTX_init (ctx);if (!EVP_CipherInit (ctx, kt,NULL ,NULL , enc)) {
src/openvpn/openssl_compat.h +28 -0
@@ -96,6 +96,34 @@ EVP_MD_CTX_new(void) }#endif +#if !defined(HAVE_EVP_CIPHER_CTX_FREE ) +/** +* Free an existing cipher context +* +* @param ctx The cipher context +*/ +static inline void +EVP_CIPHER_CTX_free (EVP_CIPHER_CTX *c) +{ +free (c); +} +#endif + +#if !defined(HAVE_EVP_CIPHER_CTX_NEW ) +/** +* Allocate a new cipher context object +* +* @return A zero'ed cipher context object +*/ +static inline EVP_CIPHER_CTX * +EVP_CIPHER_CTX_new (void ) +{ +EVP_CIPHER_CTX *ctx =NULL ; +ALLOC_OBJ_CLEAR (ctx,EVP_CIPHER_CTX ); +return ctx; +} +#endif +#if !defined(HAVE_SSL_CTX_GET_DEFAULT_PASSWD_CB_USERDATA )/** * Fetch the default password callback user data from the SSL context
Signature · 1 line
2.11.0
PATCH 7/7 OpenSSL: don't use direct access to the internal of HMAC_CTX
In reply to Emmanuel DelogetOpenSSL 1.1 does not allow us to directly access the internal of any data type, including HMAC_CTX. We have to use the defined functions to do so.
Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
--- configure.ac | 4 +++ src/openvpn/crypto.c | 4 +-- src/openvpn/crypto_backend.h | 14 ++++++++++ src/openvpn/crypto_mbedtls.c | 15 ++++++++++ src/openvpn/crypto_openssl.c | 17 ++++++++++-- src/openvpn/ntlm.c | 12 ++++---- src/openvpn/openssl_compat.h | 65 ++++++++++++++++++++++++++++++++++++++++++++ src/openvpn/ssl.c | 38 ++++++++++++++------------ 8 files changed, 140 insertions(+), 29 deletions(-)
configure.ac +4 -0
@@ -922,6 +922,10 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then [ \ EVP_CIPHER_CTX_new \ EVP_CIPHER_CTX_free \ + HMAC_CTX_new \ + HMAC_CTX_free \ + HMAC_CTX_reset \ + HMAC_CTX_init \ EVP_MD_CTX_new \ EVP_MD_CTX_free \ EVP_MD_CTX_reset \
src/openvpn/crypto.c +2 -2
@@ -854,7 +854,7 @@ init_key_ctx(struct key_ctx *ctx, struct key *key, }if (kt->digest && kt->hmac_length >0 ) { -ALLOC_OBJ (ctx->hmac, hmac_ctx_t); + ctx->hmac =hmac_ctx_new ();hmac_ctx_init (ctx->hmac, key->hmac, kt->hmac_length, kt->digest); msg(D_HANDSHAKE,
@@ -885,7 +885,7 @@ free_key_ctx(struct key_ctx *ctx)if (ctx->hmac) {hmac_ctx_cleanup (ctx->hmac); -free (ctx->hmac); +hmac_ctx_free (ctx->hmac); ctx->hmac =NULL ; } ctx->implicit_iv_len =0 ;
src/openvpn/crypto_backend.h +14 -0
@@ -584,6 +584,20 @@ void md_ctx_final(md_ctx_t *ctx, uint8_t *dst);*/ /* +* Create a new HMAC context +* +* @return A new HMAC context +*/ +hmac_ctx_t *hmac_ctx_new (void ); + +/* +* Free an existing HMAC context +* +* @param ctx HMAC context to free +*/ +void hmac_ctx_free (hmac_ctx_t *ctx); + +/* * Initialises the given HMAC context, using the given digest * and key. *
src/openvpn/crypto_mbedtls.c +15 -0
@@ -841,6 +841,21 @@ md_ctx_final(mbedtls_md_context_t *ctx, uint8_t *dst)/* * TODO: re-enable dmsg for crypto debug */ + +mbedtls_md_context_t * +hmac_ctx_new (void ) +{ +mbedtls_md_context_t *ctx; +ALLOC_OBJ (ctx, mbedtls_md_context_t); +return ctx; +} + +void +hmac_ctx_free (mbedtls_md_context_t *ctx) +{ +free (ctx); +} +void hmac_ctx_init (mbedtls_md_context_t *ctx,const uint8_t *key,int key_len,const mbedtls_md_info_t *kt)
src/openvpn/crypto_openssl.c +14 -3
@@ -911,6 +911,19 @@ md_ctx_final(EVP_MD_CTX *ctx, uint8_t *dst)* */ +HMAC_CTX * +hmac_ctx_new (void ) +{ +HMAC_CTX *ctx =HMAC_CTX_new (); +check_malloc_return (ctx); +return ctx; +} + +void +hmac_ctx_free (HMAC_CTX *ctx) +{ +HMAC_CTX_free (ctx); +} void hmac_ctx_init(HMAC_CTX *ctx, const uint8_t *key, int key_len,
@@ -918,8 +931,6 @@ hmac_ctx_init(HMAC_CTX *ctx, const uint8_t *key, int key_len, {ASSERT (NULL != kt &&NULL != ctx); -CLEAR (*ctx); -HMAC_CTX_init (ctx);HMAC_Init_ex (ctx, key, key_len, kt,NULL );
@@ -930,7 +941,7 @@ hmac_ctx_init(HMAC_CTX *ctx, const uint8_t *key, int key_len,void hmac_ctx_cleanup (HMAC_CTX *ctx) { -HMAC_CTX_cleanup (ctx); +HMAC_CTX_reset (ctx); }int
src/openvpn/ntlm.c +6 -6
@@ -86,13 +86,13 @@ static void gen_hmac_md5(const char *data, int data_len, const char *key, int key_len,char *result) { const md_kt_t *md5_kt = md_kt_get("MD5"); -hmac_ctx_t hmac_ctx; -CLEAR (hmac_ctx); +hmac_ctx_t *hmac_ctx =hmac_ctx_new (); -hmac_ctx_init (&hmac_ctx, key, key_len, md5_kt); -hmac_ctx_update (&hmac_ctx, (const unsigned char *)data, data_len); -hmac_ctx_final (&hmac_ctx, (unsigned char *)result); -hmac_ctx_cleanup (&hmac_ctx); +hmac_ctx_init (hmac_ctx, key, key_len, md5_kt); +hmac_ctx_update (hmac_ctx, (const unsigned char *)data, data_len); +hmac_ctx_final (hmac_ctx, (unsigned char *)result); +hmac_ctx_cleanup (hmac_ctx); +hmac_ctx_free (hmac_ctx); } static void
src/openvpn/openssl_compat.h +65 -0
71 lines not on this page · raw message
src/openvpn/ssl.c +20 -18
@@ -1607,8 +1607,8 @@ tls1_P_hash(const md_kt_t *md_kt, {struct gc_arena gc =gc_new ();int chunk; -hmac_ctx_t ctx; -hmac_ctx_t ctx_tmp; +hmac_ctx_t *ctx; +hmac_ctx_t *ctx_tmp;uint8_t A1 [MAX_HMAC_KEY_LENGTH ];unsigned int A1_len;
@@ -1617,8 +1617,8 @@ tls1_P_hash(const md_kt_t *md_kt,const uint8_t *out_orig = out;#endif -CLEAR (ctx); -CLEAR (ctx_tmp); + ctx =hmac_ctx_new (); + ctx_tmp =hmac_ctx_new ();dmsg (D_SHOW_KEY_SOURCE ,"tls1_P_hash sec: %s" ,format_hex (sec, sec_len,0 , &gc));dmsg (D_SHOW_KEY_SOURCE ,"tls1_P_hash seed: %s" ,format_hex (seed, seed_len,0 , &gc));
@@ -1626,36 +1626,38 @@ tls1_P_hash(const md_kt_t *md_kt, chunk =md_kt_size (md_kt); A1_len =md_kt_size (md_kt); -hmac_ctx_init (&ctx, sec, sec_len, md_kt); -hmac_ctx_init (&ctx_tmp, sec, sec_len, md_kt); +hmac_ctx_init (ctx, sec, sec_len, md_kt); +hmac_ctx_init (ctx_tmp, sec, sec_len, md_kt); -hmac_ctx_update (&ctx,seed,seed_len); -hmac_ctx_final (&ctx,A1 ); +hmac_ctx_update (ctx,seed,seed_len); +hmac_ctx_final (ctx,A1 );for (;; ) { -hmac_ctx_reset (&ctx); -hmac_ctx_reset (&ctx_tmp); -hmac_ctx_update (&ctx,A1 ,A1_len); -hmac_ctx_update (&ctx_tmp,A1 ,A1_len); -hmac_ctx_update (&ctx,seed,seed_len); +hmac_ctx_reset (ctx); +hmac_ctx_reset (ctx_tmp); +hmac_ctx_update (ctx,A1 ,A1_len); +hmac_ctx_update (ctx_tmp,A1 ,A1_len); +hmac_ctx_update (ctx,seed,seed_len);if (olen > chunk) { -hmac_ctx_final (&ctx, out); +hmac_ctx_final (ctx, out); out += chunk; olen -= chunk; -hmac_ctx_final (&ctx_tmp,A1 );/* calc the next A1 value */ +hmac_ctx_final (ctx_tmp,A1 );/* calc the next A1 value */ }else /* last one */ { -hmac_ctx_final (&ctx,A1 ); +hmac_ctx_final (ctx,A1 );memcpy (out,A1 ,olen);break ; } } -hmac_ctx_cleanup (&ctx); -hmac_ctx_cleanup (&ctx_tmp); +hmac_ctx_cleanup (ctx); +hmac_ctx_free (ctx); +hmac_ctx_cleanup (ctx_tmp); +hmac_ctx_free (ctx_tmp);secure_memzero (A1 ,sizeof (A1 ));dmsg (D_SHOW_KEY_SOURCE ,"tls1_P_hash out: %s" ,format_hex (out_orig, olen_orig,0 , &gc));
Signature · 1 line
2.11.0
Re: [Openvpn-devel] [PATCH 1/7] OpenSSL: don't use direct access to the internal of X509
In reply to Emmanuel DelogetHi,
Quoted 12 lines · Emmanuel Deloget
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including X509. We have to use the defined functions to do so.
In
x509_verify_ns_cert_type()in particular, this means that we cannot directly check for the extended flags to find whether the certificate should be used as a client or as a server certificate. We need to leverage theX509_check_purpose()API yet this API is far stricter than the currently implemented check. So far, I have not been able to find a situation where this stricter test fails (although I must admit that I haven't tested that very well).
Quoted 6 lines
We double-check the certificate purpose using "direct access" to the internal of the certificate object (of course, this is not a real direct access, but we still fetch ASN1 strings within the X509 object and we check the internal value of these strings). This allow us to warn the user if there is a discrepancy between the
X509_check_purpose()return value and our internal, less strict check.
Very nice that you found a way out of this!
Quoted 95 lines
Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
Signed-off-by Emmanuel Deloget <[email protected]...>--- configure.ac | 1 + src/openvpn/openssl_compat.h | 15 ++++++++++ src/openvpn/ssl_openssl.c | 3 +- src/openvpn/ssl_verify_openssl.c | 64 ++++++++++++++++++++++++++++++++++------ 4 files changed, 73 insertions(+), 10 deletions(-)configure.ac +1
-0@@ -922,6 +922,7 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then [ \ SSL_CTX_get_default_passwd_cb \ SSL_CTX_get_default_passwd_cb_userdata \ + X509_get0_pubkey \ X509_STORE_get0_objects \ X509_OBJECT_free \ X509_OBJECT_get_type \src/openvpn/openssl_compat.h +15
-0@@ -74,6 +74,21 @@ SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx) }#endif +#if !defined(HAVE_X509_GET0_PUBKEY ) +/** +* Get the public key from a X509 certificate +* +* @param x X509 certificate +* @return The certificate public key +*/ +static inline EVP_PKEY * +X509_get0_pubkey (const X509 *x) +{ +return (x && x->cert_info && x->cert_info->key) ? + x->cert_info->key->pkey :NULL ; +} +#endif +#if !defined(HAVE_X509_STORE_GET0_OBJECTS )/** * Fetch the X509 object stack from the X509 store src/openvpn/ssl_openssl.c +2
-1@@ -1070,7 +1070,8 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx, }/* get the public key */ -ASSERT (cert->cert_info->key->pkey);/* NULL before SSL_CTX_use_certificate() is called */ +EVP_PKEY *pkey =X509_get0_pubkey (cert); +ASSERT (pkey);/* NULL before SSL_CTX_use_certificate() is called */ pub_rsa = cert->cert_info->key->pkey->pkey.rsa;/* initialize RSA object */ src/openvpn/ssl_verify_openssl.c +7
-5@@ -294,18 +294,20 @@ backend_x509_get_serial_hex(openvpn_x509_cert_t *cert, struct gc_arena *gc)struct buffer x509_get_sha1_fingerprint (X509 *cert,struct gc_arena *gc) { -struct buffer hash =alloc_buf_gc (sizeof (cert->sha1_hash), gc); -memcpy (BPTR (&hash), cert->sha1_hash,sizeof (cert->sha1_hash)); -ASSERT (buf_inc_len (&hash,sizeof (cert->sha1_hash))); +const EVP_MD *sha1 =EVP_sha1 (); +struct buffer hash =alloc_buf_gc (EVP_MD_size (sha1), gc); +X509_digest (cert,EVP_sha1 (),BPTR (&hash),NULL ); +ASSERT (buf_inc_len (&hash,EVP_MD_size (sha1)));return hash; }struct buffer x509_get_sha256_fingerprint (X509 *cert,struct gc_arena *gc) { -struct buffer hash =alloc_buf_gc ((EVP_sha256 ())->md_size, gc); +const EVP_MD *sha256 =EVP_sha256 (); +struct buffer hash =alloc_buf_gc (EVP_MD_size (sha256), gc);X509_digest (cert,EVP_sha256 (),BPTR (&hash),NULL ); -ASSERT (buf_inc_len (&hash, (EVP_sha256 ())->md_size)); +ASSERT (buf_inc_len (&hash,EVP_MD_size (sha256)));return hash; }@@ -578,13 +580,57 @@ x509_verify_ns_cert_type(const openvpn_x509_cert_t *peer_cert, const int usage) }
src/openvpn/ssl_verify_openssl.c x509_verify_ns_cert_type(const openvpn_x509_cert_t *peer_cert, const int usage) · line 588
Quoted 10 lines
src/openvpn/ssl_verify_openssl.c +6
-2if (usage ==NS_CERT_CHECK_CLIENT ) { -return ((peer_cert->ex_flags &EXFLAG_NSCERT ) - && (peer_cert->ex_nscert &NS_SSL_CLIENT )) ?SUCCESS :FAILURE ; +/* +* Unfortunately, X509_check_purpose() does some wierd thing that +* prevent it to take a const argument +*/ +result_t result =X509_check_purpose ((X509 *)peer_cert,X509_PURPOSE_SSL_CLIENT ,0 ) ? +SUCCESS :FAILURE ;
Instead of casting away const, I think we should remove the 'const' qualifier from the function argument. The caller has a non-const peer_cert anyway, and casting away const should really be avoided.
Quoted 5 lines
src/openvpn/ssl_verify_openssl.c +5
-0+/* +* old versions of OpenSSL allow us to make the less strict check we used to +* do. If this less strict check pass, warn user that this might not be the +* case when its distribution will update to OpenSSL 1.1 +*/
src/openvpn/ssl_verify_openssl.c x509_verify_ns_cert_type(const openvpn_x509_cert_t *peer_cert, const int usage) · line 604
Quoted 10 lines
src/openvpn/ssl_verify_openssl.c +10
-0+if (result ==FAILURE ) + { +ASN1_BIT_STRING *ns; + ns =X509_get_ext_d2i ((X509 *)peer_cert, NID_netscape_cert_type,NULL ,NULL ); + result = (ns && ns->length >0 && (ns->data[0 ] &NS_SSL_CLIENT )) ?SUCCESS :FAILURE ; +if (result ==SUCCESS ) + { +msg (M_WARN ,"X509: Certificate is a client certificate yet it's purpose " +"cannot be verified (check may fail in the future)" ); + }
This seems to introduce a memory leak: ns should be free'd using ASN1_BIT_STRING_free().
Quoted 25 lines
src/openvpn/ssl_verify_openssl.c +19
-2+ } +return result; }if (usage ==NS_CERT_CHECK_SERVER ) { -return ((peer_cert->ex_flags &EXFLAG_NSCERT ) - && (peer_cert->ex_nscert &NS_SSL_SERVER )) ?SUCCESS :FAILURE ; +/* +* Unfortunately, X509_check_purpose() does some wierd thing that +* prevent it to take a const argument +*/ +result_t result =X509_check_purpose ((X509 *)peer_cert,X509_PURPOSE_SSL_SERVER ,0 ) ? +SUCCESS :FAILURE ; + +/* +* old versions of OpenSSL allow us to make the less strict check we used to +* do. If this less strict check pass, warn user that this might not be the +* case when its distribution will update to OpenSSL 1.1 +*/ +if (result ==FAILURE ) + { +ASN1_BIT_STRING *ns; + ns =X509_get_ext_d2i ((X509 *)peer_cert, NID_netscape_cert_type,NULL ,NULL ); + result = (ns && ns->length >0 && (ns->data[0 ] &NS_SSL_SERVER )) ?SUCCESS :FAILURE ;
src/openvpn/ssl_verify_openssl.c x509_verify_ns_cert_type(const openvpn_x509_cert_t *peer_cert, const int usage) · line 636
Quoted 10 lines
src/openvpn/ssl_verify_openssl.c +7
-0+if (result ==SUCCESS ) + { +msg (M_WARN ,"X509: Certificate is a server certificate yet it's purpose " +"cannot be verified (check may fail in the future)" ); + } + } +return result; }return FAILURE ;
Could you send a follow-up patch with these issues fixed?
Thanks,
-Steffan
Re: [Openvpn-devel] OpenSSL 1.1 patch set - status?
In reply to Emmanuel DelogetHi,
Quoted 6 lines · Emmanuel Deloget
Quoted 3 lines
I'm wondering where this got stuck - are you waiting for us to move forward (like, missing review of parts of the patch set), or are we waiting for you, and you've been busy?
Problem is that I'm working in a more-than-full-time manner on way-too-many-other subjects :)
Thanks for quickly sending us the current patch set. Now it's on us again.
(And yes, we fully understand the "too many projects, too many complaining customers, angry wife as well, and too little time" thing :) )
Over to Steffan now - I'm so happy that I do not have to understand OpenSSL code... ;-)
gert
Signature · 4 lines
USENET is *not* the non-clickable part of WWW!
//www.muc.de/~gert/
Gert Doering - Munich, Germany [email protected]...
fax: +49-89-35655025 [email protected]...Re: [Openvpn-devel] OpenSSL 1.1 patch set - status?
Hi Gert,
Quoted 12 lines · Gert Doering
Hi,
Quoted 6 lines · Emmanuel Deloget
Quoted 3 lines
I'm wondering where this got stuck - are you waiting for us to move forward (like, missing review of parts of the patch set), or are we waiting for you, and you've been busy?
Problem is that I'm working in a more-than-full-time manner on way-too-many-other subjects :)
Thanks for quickly sending us the current patch set. Now it's on us again.
If there is anything bad, please tell me - I should be able to do another round if needed :)
Quoted 5 lines
(And yes, we fully understand the "too many projects, too many complaining customers, angry wife as well, and too little time" thing :) )
Yeah. It seems that "somebody" limited the day length to a small value that fit on a 5 bit word. I'm wondering if this "person" was told about uint32_t...
Quoted 4 lines
Over to Steffan now - I'm so happy that I do not have to understand OpenSSL code... ;-)
Good thing is : there is nothing complex in the changes I made. I'm pretty sure you'll be able to understand both the changes and what the original code does :)
Quoted 3 lines
gert
BR,
-- Emmanuel Deloget
Re: [Openvpn-devel] OpenSSL 1.1 patch set - status?
Hi,
Quoted 22 lines · Emmanuel Deloget
Quoted 10 lines · Gert Doering
Quoted 6 lines · Emmanuel Deloget
Quoted 3 lines
I'm wondering where this got stuck - are you waiting for us to move forward (like, missing review of parts of the patch set), or are we waiting for you, and you've been busy?
Problem is that I'm working in a more-than-full-time manner on way-too-many-other subjects :)
Thanks for quickly sending us the current patch set. Now it's on us again.
If there is anything bad, please tell me - I should be able to do another round if needed :)
Quoted 2 lines
(And yes, we fully understand the "too many projects, too many complaining customers, angry wife as well, and too little time" thing :) )
Yeah. It seems that "somebody" limited the day length to a small value that fit on a 5 bit word. I'm wondering if this "person" was told about
uint32_t...
Quoted 6 lines
Quoted 2 lines
Over to Steffan now - I'm so happy that I do not have to understand OpenSSL code... ;-)
Good thing is : there is nothing complex in the changes I made. I'm pretty sure you'll be able to understand both the changes and what the original code does :)
This is probably the most polite bump mail I've ever seen :-p
Just so you know: I haven't forgotten about these - they are confronting me with my back log each time I open my mailbox... I'll get to it at some point, but in the mean time (as always) other reviewers are of course welcome to look at them too!
-Steffan
RFC PATCH 6/15 OpenSSL: don't use direct access to the internal of EVP_PKEY
In reply to [email protected]...From: Emmanuel Deloget <[email protected]...>
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including EVP_PKEY. We have to use the defined functions to do so.
Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
--- configure.ac | 2 ++ src/openvpn/openssl_compat.h | 28 ++++++++++++++++++++++++++++ src/openvpn/ssl_openssl.c | 6 +++--- 3 files changed, 33 insertions(+), 3 deletions(-)
configure.ac +2 -0
@@ -906,6 +906,8 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then X509_STORE_get0_objects \ X509_OBJECT_free \ X509_OBJECT_get_type \ + EVP_PKEY_get0_RSA \ + EVP_PKEY_get0_DSA \ RSA_meth_new \ RSA_meth_free \ RSA_meth_set_pub_enc \
src/openvpn/openssl_compat.h +28 -0
@@ -134,6 +134,34 @@ X509_OBJECT_get_type(const X509_OBJECT *obj) }#endif +#if !defined(HAVE_EVP_PKEY_GET0_RSA ) +/** +* Get the RSA object of a public key +* +* @param pkey Public key object +* @return The underlying RSA object +*/ +static inline RSA * +EVP_PKEY_get0_RSA (EVP_PKEY *pkey) +{ +return pkey ? pkey->pkey.rsa :NULL ; +} +#endif + +#if !defined(HAVE_EVP_PKEY_GET0_DSA ) +/** +* Get the DSA object of a public key +* +* @param pkey Public key object +* @return The underlying DSA object +*/ +static inline DSA * +EVP_PKEY_get0_DSA (EVP_PKEY *pkey) +{ +return pkey ? pkey->pkey.dsa :NULL ; +} +#endif +#if !defined(HAVE_RSA_METH_NEW )/** * Allocate a new RSA method object
src/openvpn/ssl_openssl.c +3 -3
@@ -1075,7 +1075,7 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx,/* get the public key */ EVP_PKEY *pkey =X509_get0_pubkey (cert);ASSERT (pkey);/* NULL before SSL_CTX_use_certificate() is called */ - pub_rsa = cert->cert_info->key->pkey->pkey.rsa; + pub_rsa =EVP_PKEY_get0_RSA (pkey);/* initialize RSA object */ rsa->n =BN_dup (pub_rsa->n);
@@ -1680,13 +1680,13 @@ print_details(struct key_state_ssl *ks_ssl, const char *prefix)EVP_PKEY *pkey =X509_get_pubkey (cert);if (pkey !=NULL ) { -if (pkey->type ==EVP_PKEY_RSA && pkey->pkey.rsa !=NULL +if (EVP_PKEY_id (pkey) ==EVP_PKEY_RSA &&EVP_PKEY_get0_RSA (pkey) !=NULL && pkey->pkey.rsa->n !=NULL ) {openvpn_snprintf (s2,sizeof (s2),", %d bit RSA" ,BN_num_bits (pkey->pkey.rsa->n)); } -else if (pkey->type ==EVP_PKEY_DSA && pkey->pkey.dsa !=NULL +else if (EVP_PKEY_id (pkey) ==EVP_PKEY_DSA &&EVP_PKEY_get0_DSA (pkey) !=NULL && pkey->pkey.dsa->p !=NULL ) { openvpn_snprintf(s2, sizeof(s2), ", %d bit DSA",
Signature · 1 line
2.7.4
RFC PATCH 7/15 OpenSSL: don't use direct access to the internal of RSA
In reply to [email protected]...From: Emmanuel Deloget <[email protected]...>
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including RSA. We have to use the defined functions to do so.
Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
--- configure.ac | 3 ++ src/openvpn/openssl_compat.h | 84 ++++++++++++++++++++++++++++++++++++++++++++ src/openvpn/ssl_openssl.c | 25 ++++++++----- 3 files changed, 104 insertions(+), 8 deletions(-)
configure.ac +3 -0
@@ -908,6 +908,9 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then X509_OBJECT_get_type \ EVP_PKEY_get0_RSA \ EVP_PKEY_get0_DSA \ + RSA_set_flags \ + RSA_get0_key \ + RSA_set0_key \ RSA_meth_new \ RSA_meth_free \ RSA_meth_set_pub_enc \
src/openvpn/openssl_compat.h +84 -0
90 lines not on this page · raw message
src/openvpn/ssl_openssl.c +17 -8
@@ -978,8 +978,9 @@ rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, istatic int rsa_finish (RSA *rsa) { -RSA_meth_free (rsa->meth); - rsa->meth =NULL ; +RSA_METHOD *meth = (RSA_METHOD *)RSA_get_method (rsa); +RSA_meth_free (meth); +RSA_set_method (rsa,NULL );return 1 ; }
@@ -1078,8 +1079,11 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx, pub_rsa =EVP_PKEY_get0_RSA (pkey);/* initialize RSA object */ - rsa->n =BN_dup (pub_rsa->n); - rsa->flags |=RSA_FLAG_EXT_PKEY ; +const BIGNUM *n =NULL ; +const BIGNUM *e =NULL ; +RSA_get0_key (pub_rsa, &n, &e,NULL ); +RSA_set0_key (rsa,BN_dup (n),BN_dup (e),NULL ); +RSA_set_flags (rsa,RSA_flags (rsa) |RSA_FLAG_EXT_PKEY );if (!RSA_set_method (rsa, rsa_meth)) { goto err;
@@ -1680,11 +1684,16 @@ print_details(struct key_state_ssl *ks_ssl, const char *prefix)EVP_PKEY *pkey =X509_get_pubkey (cert);if (pkey !=NULL ) { -if (EVP_PKEY_id (pkey) ==EVP_PKEY_RSA &&EVP_PKEY_get0_RSA (pkey) !=NULL - && pkey->pkey.rsa->n !=NULL ) +if (EVP_PKEY_id (pkey) ==EVP_PKEY_RSA &&EVP_PKEY_get0_RSA (pkey) !=NULL ) { -openvpn_snprintf (s2,sizeof (s2),", %d bit RSA" , -BN_num_bits (pkey->pkey.rsa->n)); +RSA *rsa =EVP_PKEY_get0_RSA (pkey); +const BIGNUM *n =NULL ; +RSA_get0_key (rsa, &n,NULL ,NULL ); +if (n !=NULL ) + { +openvpn_snprintf (s2,sizeof (s2),", %d bit RSA" , +BN_num_bits (n)); + } }else if (EVP_PKEY_id (pkey) ==EVP_PKEY_DSA &&EVP_PKEY_get0_DSA (pkey) !=NULL && pkey->pkey.dsa->p !=NULL )
Signature · 1 line
2.7.4
RFC PATCH 8/15 OpenSSL: don't use direct access to the internal of DSA
In reply to [email protected]...From: Emmanuel Deloget <[email protected]...>
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including DSA. We have to use the defined functions to do so.
Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
--- configure.ac | 1 + src/openvpn/openssl_compat.h | 28 ++++++++++++++++++++++++++++ src/openvpn/ssl_openssl.c | 13 +++++++++---- 3 files changed, 38 insertions(+), 4 deletions(-)
configure.ac +1 -0
@@ -911,6 +911,7 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then RSA_set_flags \ RSA_get0_key \ RSA_set0_key \ + DSA_get0_pqg \ RSA_meth_new \ RSA_meth_free \ RSA_meth_set_pub_enc \
src/openvpn/openssl_compat.h +28 -0
@@ -246,6 +246,34 @@ RSA_set0_key(RSA *rsa, BIGNUM *n, BIGNUM *e, BIGNUM *d) }#endif +#if !defined(HAVE_DSA_GET0_PQG ) +/** +* Get the DSA parameters +* +* @param dsa The DSA object +* @param p The @c p parameter +* @param q The @c q parameter +* @param g The @c g parameter +*/ +static inline void +DSA_get0_pqg (const DSA *dsa,const BIGNUM **p, +const BIGNUM **q,const BIGNUM **g) +{ +if (p !=NULL ) + { + *p = dsa ? dsa->p :NULL ; + } +if (q !=NULL ) + { + *q = dsa ? dsa->q :NULL ; + } +if (g !=NULL ) + { + *g = dsa ? dsa->g :NULL ; + } +} +#endif +#if !defined(HAVE_RSA_METH_NEW )/** * Allocate a new RSA method object
src/openvpn/ssl_openssl.c +9 -4
@@ -1695,11 +1695,16 @@ print_details(struct key_state_ssl *ks_ssl, const char *prefix) BN_num_bits(n)); } } -else if (EVP_PKEY_id (pkey) ==EVP_PKEY_DSA &&EVP_PKEY_get0_DSA (pkey) !=NULL - && pkey->pkey.dsa->p !=NULL ) +else if (EVP_PKEY_id (pkey) ==EVP_PKEY_DSA &&EVP_PKEY_get0_DSA (pkey) !=NULL ) { -openvpn_snprintf (s2,sizeof (s2),", %d bit DSA" , -BN_num_bits (pkey->pkey.dsa->p)); +DSA *dsa =EVP_PKEY_get0_DSA (pkey); +const BIGNUM *p =NULL ; +DSA_get0_pqg (dsa, &p,NULL ,NULL ); +if (p !=NULL ) + { +openvpn_snprintf (s2,sizeof (s2),", %d bit DSA" , +BN_num_bits (p)); + } }EVP_PKEY_free (pkey); }
Signature · 1 line
2.7.4
RFC PATCH 9/15 OpenSSL: don't use direct access to the internal of X509_STORE_CTX
In reply to [email protected]...From: Emmanuel Deloget <[email protected]...>
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including X509_STORE_CTX. We have to use the defined functions to do so.
Fortunately, these functions have existed since the dawn of time so we don't have any compatibility issue here.
--- src/openvpn/ssl_verify_openssl.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)
src/openvpn/ssl_verify_openssl.c +10 -9
@@ -62,14 +62,15 @@ verify_callback(int preverify_ok, X509_STORE_CTX *ctx) session = (struct tls_session *)SSL_get_ex_data (ssl, mydata_index);ASSERT (session); -struct buffer cert_hash =x509_get_sha256_fingerprint (ctx->current_cert, &gc); -cert_hash_remember (session, ctx->error_depth, &cert_hash); +X509 *current_cert =X509_STORE_CTX_get_current_cert (ctx); +struct buffer cert_hash =x509_get_sha256_fingerprint (current_cert, &gc); +cert_hash_remember (session,X509_STORE_CTX_get_error_depth (ctx), &cert_hash);/* did peer present cert which was signed by our root cert? */ if (!preverify_ok) {/* get the X509 name */ -char *subject =x509_get_subject (ctx->current_cert, &gc); +char *subject =x509_get_subject (current_cert, &gc);if (!subject) {
@@ -77,11 +78,11 @@ verify_callback(int preverify_ok, X509_STORE_CTX *ctx) }/* Log and ignore missing CRL errors */ -if (ctx->error ==X509_V_ERR_UNABLE_TO_GET_CRL ) +if (X509_STORE_CTX_get_error (ctx) ==X509_V_ERR_UNABLE_TO_GET_CRL ) {msg (D_TLS_DEBUG_LOW ,"VERIFY WARNING: depth=%d, %s: %s" , - ctx->error_depth, -X509_verify_cert_error_string (ctx->error), +X509_STORE_CTX_get_error_depth (ctx), +X509_verify_cert_error_string (X509_STORE_CTX_get_error (ctx)), subject); ret =1 ; goto cleanup;
@@ -89,8 +90,8 @@ verify_callback(int preverify_ok, X509_STORE_CTX *ctx)/* Remote site specified a certificate, but it's not correct */ msg (D_TLS_ERRORS ,"VERIFY ERROR: depth=%d, error=%s: %s" , - ctx->error_depth, -X509_verify_cert_error_string (ctx->error), +X509_STORE_CTX_get_error_depth (ctx), +X509_verify_cert_error_string (X509_STORE_CTX_get_error (ctx)), subject);ERR_clear_error ();
@@ -99,7 +100,7 @@ verify_callback(int preverify_ok, X509_STORE_CTX *ctx) goto cleanup; } -if (SUCCESS !=verify_cert (session, ctx->current_cert, ctx->error_depth)) +if (SUCCESS !=verify_cert (session, current_cert,X509_STORE_CTX_get_error_depth (ctx))) { goto cleanup; }
Signature · 1 line
2.7.4
Re: [Openvpn-devel] [RFC PATCH v1 09/15] OpenSSL: don't use direct access to the internal of X509_STORE_CTX
Hi,
Quoted 65 lines · On 17-02-17 23:00, [email protected]... wrote:
From: Emmanuel Deloget <[email protected]...>
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including
X509_STORE_CTX. We have to use the defined functions to do so.Fortunately, these functions have existed since the dawn of time so we don't have any compatibility issue here.
Signed-off-by Emmanuel Deloget <[email protected]...>--- src/openvpn/ssl_verify_openssl.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)src/openvpn/ssl_verify_openssl.c +9
-8@@ -62,14 +62,15 @@ verify_callback(int preverify_ok, X509_STORE_CTX *ctx) session = (struct tls_session *)SSL_get_ex_data (ssl, mydata_index);ASSERT (session); -struct buffer cert_hash =x509_get_sha256_fingerprint (ctx->current_cert, &gc); -cert_hash_remember (session, ctx->error_depth, &cert_hash); +X509 *current_cert =X509_STORE_CTX_get_current_cert (ctx); +struct buffer cert_hash =x509_get_sha256_fingerprint (current_cert, &gc); +cert_hash_remember (session,X509_STORE_CTX_get_error_depth (ctx), &cert_hash);/* did peer present cert which was signed by our root cert? */ if (!preverify_ok) {/* get the X509 name */ -char *subject =x509_get_subject (ctx->current_cert, &gc); +char *subject =x509_get_subject (current_cert, &gc);if (!subject) {@@ -77,11 +78,11 @@ verify_callback(int preverify_ok, X509_STORE_CTX *ctx) }/* Log and ignore missing CRL errors */ -if (ctx->error ==X509_V_ERR_UNABLE_TO_GET_CRL ) +if (X509_STORE_CTX_get_error (ctx) ==X509_V_ERR_UNABLE_TO_GET_CRL ) {msg (D_TLS_DEBUG_LOW ,"VERIFY WARNING: depth=%d, %s: %s" , - ctx->error_depth, -X509_verify_cert_error_string (ctx->error), +X509_STORE_CTX_get_error_depth (ctx), +X509_verify_cert_error_string (X509_STORE_CTX_get_error (ctx)), subject); ret =1 ; goto cleanup;@@ -89,8 +90,8 @@ verify_callback(int preverify_ok, X509_STORE_CTX *ctx)/* Remote site specified a certificate, but it's not correct */ msg (D_TLS_ERRORS ,"VERIFY ERROR: depth=%d, error=%s: %s" , - ctx->error_depth, -X509_verify_cert_error_string (ctx->error), +X509_STORE_CTX_get_error_depth (ctx), +X509_verify_cert_error_string (X509_STORE_CTX_get_error (ctx)), subject);ERR_clear_error ();
src/openvpn/ssl_verify_openssl.c verify_callback(int preverify_ok, X509_STORE_CTX *ctx) · line 106
Quoted 8 lines
src/openvpn/ssl_verify_openssl.c +1
-1@@ -99,7 +100,7 @@ verify_callback(int preverify_ok, X509_STORE_CTX *ctx) goto cleanup; } -if (SUCCESS !=verify_cert (session, ctx->current_cert, ctx->error_depth)) +if (SUCCESS !=verify_cert (session, current_cert,X509_STORE_CTX_get_error_depth (ctx))) { goto cleanup; }
ACK. Changes look good and tested against OpenSSL 0.9.8, 1.0.0, 1.0.1 and 1.0.2.
-Steffan
Re: [Openvpn-devel] [RFC PATCH v1 09/15] OpenSSL: don't use direct access to the internal of X509_STORE_CTX
Steffan Karger <[email protected]...> on Tue, 2017/02/21 22:30:
Quoted 2 lines
ACK. Changes look good and tested against OpenSSL 0.9.8, 1.0.0, 1.0.1 and 1.0.2.
You answered to a patch in the middle of a series. Does this ACK apply to the complete series or just this patch?
Signature · 3 lines
main(a){char*c=/* Schoene Gruesse */"B?IJj;MEH"
"CX:;",b;for(a/* Best regards my address: */=0;b=c[a++];)
putchar(b-1/(/* Chris cc -ox -xc - && ./x */b/42*2-3)*42);}Re: [Openvpn-devel] [RFC PATCH v1 09/15] OpenSSL: don't use direct access to the internal of X509_STORE_CTX
Quoted 6 lines · Christian Hesse
Steffan Karger <[email protected]...> on Tue, 2017/02/21 22:30:
Quoted 2 lines
ACK. Changes look good and tested against OpenSSL 0.9.8, 1.0.0, 1.0.1 and 1.0.2.
You answered to a patch in the middle of a series. Does this ACK apply to the complete series or just this patch?
Just this one. Not much brains left last night, so I only reviewed this rather simple and independent patch out of the series :)
-Steffan
[Openvpn-devel] [PATCH applied] Re: OpenSSL: don't use direct access to the internal of X509_STORE_CTX
In reply to [email protected]...Your patch has been applied to the master and release/2.4 branch.
commit 88046ad9e8e333259ae6fb4a295a9931a1a0e47f (master) commit 58efba5013f6dae4136cc038af9ffd23796cbc0d (release/2.4)
Author: Emmanuel Deloget Date: Fri Feb 17 23:00:48 2017 +0100
OpenSSL: don't use direct access to the internal of X509_STORE_CTX
Signed-off-by: Emmanuel Deloget <[email protected]...>
Acked-by: Steffan Karger <[email protected]...>
Message-Id: <11477a0a3cf636572c84e0110a6f1b726bc60c2c.1487368114.git.logout@...260...>
URL: https://www.mail-archive.com/[email protected]/msg14085.html
Signed-off-by: Gert Doering <[email protected]...>--
kind regards,
Gert Doering
RFC PATCH 10/15 OpenSSL: don't use direct access to the internal of EVP_MD_CTX
In reply to [email protected]...From: Emmanuel Deloget <[email protected]...>
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including EVP_MD_CTX. We have to use the defined functions to do so.
Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
--- configure.ac | 3 ++ src/openvpn/crypto_backend.h | 14 ++++++++ src/openvpn/crypto_mbedtls.c | 12 +++++++ src/openvpn/crypto_openssl.c | 18 ++++++++-- src/openvpn/httpdigest.c | 78 +++++++++++++++++++++++--------------------- src/openvpn/misc.c | 14 ++++---- src/openvpn/openssl_compat.h | 50 ++++++++++++++++++++++++++++ src/openvpn/openvpn.h | 2 +- src/openvpn/push.c | 11 ++++--- 9 files changed, 150 insertions(+), 52 deletions(-)
configure.ac +3 -0
@@ -900,6 +900,9 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then AC_CHECK_FUNCS( [ \ + EVP_MD_CTX_new \ + EVP_MD_CTX_free \ + EVP_MD_CTX_reset \ SSL_CTX_get_default_passwd_cb \ SSL_CTX_get_default_passwd_cb_userdata \ X509_get0_pubkey \
src/openvpn/crypto_backend.h +14 -0
@@ -502,6 +502,20 @@ int md_kt_size(const md_kt_t *kt);int md_full (const md_kt_t *kt,const uint8_t *src,int src_len,uint8_t *dst);/* +* Allocate a new message digest context +* +* @return a new zeroed MD context +*/ +md_ctx_t *md_ctx_new (void ); + +/* +* Free an existing, non-null message digest context +* +* @param ctx Message digest context +*/ +void md_ctx_free (md_ctx_t *ctx); + +/* * Initialises the given message digest context. * * @param ctx Message digest context
src/openvpn/crypto_mbedtls.c +12 -0
@@ -766,6 +766,18 @@ md_full(const md_kt_t *kt, const uint8_t *src, int src_len, uint8_t *dst)return 0 ==mbedtls_md (kt, src, src_len, dst); } +mbedtls_md_context_t * +md_ctx_new (void ) +{ +mbedtls_md_context_t *ctx; +ALLOC_OBJ_CLEAR (ctx, mbedtls_md_context_t); +return ctx; +} + +void md_ctx_free (mbedtls_md_context_t *ctx) +{ +free (ctx); +}void md_ctx_init (mbedtls_md_context_t *ctx,const mbedtls_md_info_t *kt)
src/openvpn/crypto_openssl.c +15 -3
@@ -42,6 +42,7 @@#include "integer.h" #include "crypto.h" #include "crypto_backend.h" +#include "openssl_compat.h" #include <openssl/des.h> #include <openssl/err.h>
@@ -846,13 +847,24 @@ md_full(const EVP_MD *kt, const uint8_t *src, int src_len, uint8_t *dst)return EVP_Digest (src, src_len, dst, &in_md_len, kt,NULL ); } +EVP_MD_CTX * +md_ctx_new (void ) +{ +EVP_MD_CTX *ctx =EVP_MD_CTX_new (); +check_malloc_return (ctx); +return ctx; +} + +void md_ctx_free (EVP_MD_CTX *ctx) +{ +EVP_MD_CTX_free (ctx); +} +void md_ctx_init (EVP_MD_CTX *ctx,const EVP_MD *kt) {ASSERT (NULL != ctx &&NULL != kt); -CLEAR (*ctx); -EVP_MD_CTX_init (ctx);EVP_DigestInit (ctx, kt); }
@@ -860,7 +872,7 @@ md_ctx_init(EVP_MD_CTX *ctx, const EVP_MD *kt)void md_ctx_cleanup (EVP_MD_CTX *ctx) { -EVP_MD_CTX_cleanup (ctx); +EVP_MD_CTX_reset (ctx); }int
src/openvpn/httpdigest.c +40 -38
107 lines not on this page · raw message
src/openvpn/misc.c +8 -6
@@ -1439,7 +1439,7 @@ get_user_pass_auto_userid(struct user_pass *up, const char *tag)static const uint8_t hashprefix[] ="AUTO_USERID_DIGEST" ;const md_kt_t *md5_kt =md_kt_get ("MD5" ); -md_ctx_t ctx; +md_ctx_t *ctx;CLEAR (*up);buf_set_write (&buf, (uint8_t *)up->username,USER_PASS_LEN );
@@ -1447,11 +1447,13 @@ get_user_pass_auto_userid(struct user_pass *up, const char *tag)if (get_default_gateway_mac_addr (macaddr)) {dmsg (D_AUTO_USERID ,"GUPAU: macaddr=%s" ,format_hex_ex (macaddr,sizeof (macaddr),0 ,1 ,":" , &gc)); -md_ctx_init (&ctx, md5_kt); -md_ctx_update (&ctx, hashprefix,sizeof (hashprefix) -1 ); -md_ctx_update (&ctx, macaddr,sizeof (macaddr)); -md_ctx_final (&ctx, digest); - md_ctx_cleanup(&ctx) + ctx =md_ctx_new (); +md_ctx_init (ctx, md5_kt); +md_ctx_update (ctx, hashprefix,sizeof (hashprefix) -1 ); +md_ctx_update (ctx, macaddr,sizeof (macaddr)); +md_ctx_final (ctx, digest); +md_ctx_cleanup (ctx); +md_ctx_free (ctx);buf_printf (&buf,"%s" ,format_hex_ex (digest,sizeof (digest),0 ,256 ," " , &gc)); }else
src/openvpn/openssl_compat.h +50 -0
56 lines not on this page · raw message
src/openvpn/openvpn.h +1 -1
@@ -472,7 +472,7 @@ struct context_2/* hash of pulled options, so we can compare when options change */ bool pulled_options_digest_init_done; -md_ctx_t pulled_options_state; +md_ctx_t *pulled_options_state;struct sha256_digest pulled_options_digest;struct event_timeout scheduled_exit;
src/openvpn/push.c +7 -4
@@ -722,7 +722,8 @@ process_incoming_push_msg(struct context *c,struct buffer buf_orig = buf;if (!c->c2.pulled_options_digest_init_done) { -md_ctx_init (&c->c2.pulled_options_state,md_kt_get ("SHA256" )); + c->c2.pulled_options_state =md_ctx_new (); +md_ctx_init (c->c2.pulled_options_state,md_kt_get ("SHA256" )); c->c2.pulled_options_digest_init_done = true; }if (!c->c2.did_pre_pull_restore)
@@ -736,14 +737,16 @@ process_incoming_push_msg(struct context *c, option_types_found, c->c2.es)) { -push_update_digest (&c->c2.pulled_options_state, &buf_orig, +push_update_digest (c->c2.pulled_options_state, &buf_orig, &c->options);switch (c->options.push_continuation) {case 0 :case 1 : -md_ctx_final (&c->c2.pulled_options_state, c->c2.pulled_options_digest.digest); -md_ctx_cleanup (&c->c2.pulled_options_state); +md_ctx_final (c->c2.pulled_options_state, c->c2.pulled_options_digest.digest); +md_ctx_cleanup (c->c2.pulled_options_state); +md_ctx_free (c->c2.pulled_options_state); + c->c2.pulled_options_state =NULL ; c->c2.pulled_options_digest_init_done = false; ret =PUSH_MSG_REPLY ;break ;
Signature · 1 line
2.7.4
RFC PATCH 11/15 OpenSSL: don't use direct access to the internal of EVP_CIPHER_CTX
In reply to [email protected]...From: Emmanuel Deloget <[email protected]...>
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including EVP_CIPHER_CTX. We have to use the defined functions to do so.
Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
--- configure.ac | 2 ++ src/openvpn/crypto.c | 4 ++-- src/openvpn/crypto_backend.h | 14 ++++++++++++++ src/openvpn/crypto_mbedtls.c | 13 +++++++++++++ src/openvpn/crypto_openssl.c | 15 +++++++++++++-- src/openvpn/openssl_compat.h | 28 ++++++++++++++++++++++++++++ 6 files changed, 72 insertions(+), 4 deletions(-)
configure.ac +2 -0
@@ -900,6 +900,8 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then AC_CHECK_FUNCS( [ \ + EVP_CIPHER_CTX_new \ + EVP_CIPHER_CTX_free \ EVP_MD_CTX_new \ EVP_MD_CTX_free \ EVP_MD_CTX_reset \
src/openvpn/crypto.c +2 -2
@@ -820,7 +820,7 @@ init_key_ctx(struct key_ctx *ctx, struct key *key,if (kt->cipher && kt->cipher_length >0 ) { -ALLOC_OBJ (ctx->cipher, cipher_ctx_t); + ctx->cipher =cipher_ctx_new ();cipher_ctx_init (ctx->cipher, key->cipher, kt->cipher_length, kt->cipher, enc);
@@ -869,7 +869,7 @@ free_key_ctx(struct key_ctx *ctx)if (ctx->cipher) {cipher_ctx_cleanup (ctx->cipher); -free (ctx->cipher); +cipher_ctx_free (ctx->cipher); ctx->cipher =NULL ; }if (ctx->hmac)
src/openvpn/crypto_backend.h +14 -0
@@ -295,6 +295,20 @@ bool cipher_kt_mode_aead(const cipher_kt_t *cipher);*/ /** +* Allocate a new cipher context +* +* @return a new cipher context +*/ +cipher_ctx_t *cipher_ctx_new (void ); + +/** +* Free a cipher context +* +* @param ctx Cipher context. +*/ +void cipher_ctx_free (cipher_ctx_t *ctx); + +/** * Initialise a cipher context, based on the given key and key type. * * @param ctx Cipher context. May not be NULL
src/openvpn/crypto_mbedtls.c +13 -0
@@ -509,6 +509,19 @@ cipher_kt_mode_aead(const cipher_kt_t *cipher)* */ +mbedtls_cipher_context_t * +cipher_ctx_new (void ) +{ +mbedtls_cipher_context_t *ctx; +ALLOC_OBJ (ctx, mbedtls_cipher_context_t); +return ctx; +} + +void +cipher_ctx_free (mbedtls_cipher_context_t *ctx) +{ +free (ctx); +} void cipher_ctx_init(mbedtls_cipher_context_t *ctx, uint8_t *key, int key_len,
src/openvpn/crypto_openssl.c +13 -2
@@ -653,6 +653,19 @@ cipher_kt_mode_aead(const cipher_kt_t *cipher)* */ +cipher_ctx_t * +cipher_ctx_new (void ) +{ +EVP_CIPHER_CTX *ctx =EVP_CIPHER_CTX_new (); +check_malloc_return (ctx); +return ctx; +} + +void +cipher_ctx_free (EVP_CIPHER_CTX *ctx) +{ +EVP_CIPHER_CTX_free (ctx); +} void cipher_ctx_init(EVP_CIPHER_CTX *ctx, uint8_t *key, int key_len,
@@ -660,8 +673,6 @@ cipher_ctx_init(EVP_CIPHER_CTX *ctx, uint8_t *key, int key_len, {ASSERT (NULL != kt &&NULL != ctx); -CLEAR (*ctx); -EVP_CIPHER_CTX_init (ctx);if (!EVP_CipherInit (ctx, kt,NULL ,NULL , enc)) {
src/openvpn/openssl_compat.h +28 -0
@@ -96,6 +96,34 @@ EVP_MD_CTX_new(void) }#endif +#if !defined(HAVE_EVP_CIPHER_CTX_FREE ) +/** +* Free an existing cipher context +* +* @param ctx The cipher context +*/ +static inline void +EVP_CIPHER_CTX_free (EVP_CIPHER_CTX *c) +{ +free (c); +} +#endif + +#if !defined(HAVE_EVP_CIPHER_CTX_NEW ) +/** +* Allocate a new cipher context object +* +* @return A zero'ed cipher context object +*/ +static inline EVP_CIPHER_CTX * +EVP_CIPHER_CTX_new (void ) +{ +EVP_CIPHER_CTX *ctx =NULL ; +ALLOC_OBJ_CLEAR (ctx,EVP_CIPHER_CTX ); +return ctx; +} +#endif +#if !defined(HAVE_SSL_CTX_GET_DEFAULT_PASSWD_CB_USERDATA )/** * Fetch the default password callback user data from the SSL context
Signature · 1 line
2.7.4
RFC PATCH 12/15 OpenSSL: don't use direct access to the internal of HMAC_CTX
In reply to [email protected]...From: Emmanuel Deloget <[email protected]...>
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including HMAC_CTX. We have to use the defined functions to do so.
Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
--- configure.ac | 4 +++ src/openvpn/crypto.c | 4 +-- src/openvpn/crypto_backend.h | 14 ++++++++++ src/openvpn/crypto_mbedtls.c | 15 ++++++++++ src/openvpn/crypto_openssl.c | 17 ++++++++++-- src/openvpn/ntlm.c | 12 ++++---- src/openvpn/openssl_compat.h | 65 ++++++++++++++++++++++++++++++++++++++++++++ src/openvpn/ssl.c | 38 ++++++++++++++------------ 8 files changed, 140 insertions(+), 29 deletions(-)
configure.ac +4 -0
@@ -902,6 +902,10 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then [ \ EVP_CIPHER_CTX_new \ EVP_CIPHER_CTX_free \ + HMAC_CTX_new \ + HMAC_CTX_free \ + HMAC_CTX_reset \ + HMAC_CTX_init \ EVP_MD_CTX_new \ EVP_MD_CTX_free \ EVP_MD_CTX_reset \
src/openvpn/crypto.c +2 -2
@@ -844,7 +844,7 @@ init_key_ctx(struct key_ctx *ctx, struct key *key, }if (kt->digest && kt->hmac_length >0 ) { -ALLOC_OBJ (ctx->hmac, hmac_ctx_t); + ctx->hmac =hmac_ctx_new ();hmac_ctx_init (ctx->hmac, key->hmac, kt->hmac_length, kt->digest); msg(D_HANDSHAKE,
@@ -875,7 +875,7 @@ free_key_ctx(struct key_ctx *ctx)if (ctx->hmac) {hmac_ctx_cleanup (ctx->hmac); -free (ctx->hmac); +hmac_ctx_free (ctx->hmac); ctx->hmac =NULL ; } ctx->implicit_iv_len =0 ;
src/openvpn/crypto_backend.h +14 -0
@@ -578,6 +578,20 @@ void md_ctx_final(md_ctx_t *ctx, uint8_t *dst);*/ /* +* Create a new HMAC context +* +* @return A new HMAC context +*/ +hmac_ctx_t *hmac_ctx_new (void ); + +/* +* Free an existing HMAC context +* +* @param ctx HMAC context to free +*/ +void hmac_ctx_free (hmac_ctx_t *ctx); + +/* * Initialises the given HMAC context, using the given digest * and key. *
src/openvpn/crypto_mbedtls.c +15 -0
@@ -841,6 +841,21 @@ md_ctx_final(mbedtls_md_context_t *ctx, uint8_t *dst)/* * TODO: re-enable dmsg for crypto debug */ + +mbedtls_md_context_t * +hmac_ctx_new (void ) +{ +mbedtls_md_context_t *ctx; +ALLOC_OBJ (ctx, mbedtls_md_context_t); +return ctx; +} + +void +hmac_ctx_free (mbedtls_md_context_t *ctx) +{ +free (ctx); +} +void hmac_ctx_init (mbedtls_md_context_t *ctx,const uint8_t *key,int key_len,const mbedtls_md_info_t *kt)
src/openvpn/crypto_openssl.c +14 -3
@@ -913,6 +913,19 @@ md_ctx_final(EVP_MD_CTX *ctx, uint8_t *dst)* */ +HMAC_CTX * +hmac_ctx_new (void ) +{ +HMAC_CTX *ctx =HMAC_CTX_new (); +check_malloc_return (ctx); +return ctx; +} + +void +hmac_ctx_free (HMAC_CTX *ctx) +{ +HMAC_CTX_free (ctx); +} void hmac_ctx_init(HMAC_CTX *ctx, const uint8_t *key, int key_len,
@@ -920,8 +933,6 @@ hmac_ctx_init(HMAC_CTX *ctx, const uint8_t *key, int key_len, {ASSERT (NULL != kt &&NULL != ctx); -CLEAR (*ctx); -HMAC_CTX_init (ctx);HMAC_Init_ex (ctx, key, key_len, kt,NULL );
@@ -932,7 +943,7 @@ hmac_ctx_init(HMAC_CTX *ctx, const uint8_t *key, int key_len,void hmac_ctx_cleanup (HMAC_CTX *ctx) { -HMAC_CTX_cleanup (ctx); +HMAC_CTX_reset (ctx); }int
src/openvpn/ntlm.c +6 -6
@@ -86,13 +86,13 @@ static void gen_hmac_md5(const char *data, int data_len, const char *key, int key_len,char *result) { const md_kt_t *md5_kt = md_kt_get("MD5"); -hmac_ctx_t hmac_ctx; -CLEAR (hmac_ctx); +hmac_ctx_t *hmac_ctx =hmac_ctx_new (); -hmac_ctx_init (&hmac_ctx, key, key_len, md5_kt); -hmac_ctx_update (&hmac_ctx, (const unsigned char *)data, data_len); -hmac_ctx_final (&hmac_ctx, (unsigned char *)result); -hmac_ctx_cleanup (&hmac_ctx); +hmac_ctx_init (hmac_ctx, key, key_len, md5_kt); +hmac_ctx_update (hmac_ctx, (const unsigned char *)data, data_len); +hmac_ctx_final (hmac_ctx, (unsigned char *)result); +hmac_ctx_cleanup (hmac_ctx); +hmac_ctx_free (hmac_ctx); } static void
src/openvpn/openssl_compat.h +65 -0
71 lines not on this page · raw message
src/openvpn/ssl.c +20 -18
@@ -1614,8 +1614,8 @@ tls1_P_hash(const md_kt_t *md_kt, {struct gc_arena gc =gc_new ();int chunk; -hmac_ctx_t ctx; -hmac_ctx_t ctx_tmp; +hmac_ctx_t *ctx; +hmac_ctx_t *ctx_tmp;uint8_t A1 [MAX_HMAC_KEY_LENGTH ];unsigned int A1_len;
@@ -1624,8 +1624,8 @@ tls1_P_hash(const md_kt_t *md_kt,const uint8_t *out_orig = out;#endif -CLEAR (ctx); -CLEAR (ctx_tmp); + ctx =hmac_ctx_new (); + ctx_tmp =hmac_ctx_new ();dmsg (D_SHOW_KEY_SOURCE ,"tls1_P_hash sec: %s" ,format_hex (sec, sec_len,0 , &gc));dmsg (D_SHOW_KEY_SOURCE ,"tls1_P_hash seed: %s" ,format_hex (seed, seed_len,0 , &gc));
@@ -1633,36 +1633,38 @@ tls1_P_hash(const md_kt_t *md_kt, chunk =md_kt_size (md_kt); A1_len =md_kt_size (md_kt); -hmac_ctx_init (&ctx, sec, sec_len, md_kt); -hmac_ctx_init (&ctx_tmp, sec, sec_len, md_kt); +hmac_ctx_init (ctx, sec, sec_len, md_kt); +hmac_ctx_init (ctx_tmp, sec, sec_len, md_kt); -hmac_ctx_update (&ctx,seed,seed_len); -hmac_ctx_final (&ctx,A1 ); +hmac_ctx_update (ctx,seed,seed_len); +hmac_ctx_final (ctx,A1 );for (;; ) { -hmac_ctx_reset (&ctx); -hmac_ctx_reset (&ctx_tmp); -hmac_ctx_update (&ctx,A1 ,A1_len); -hmac_ctx_update (&ctx_tmp,A1 ,A1_len); -hmac_ctx_update (&ctx,seed,seed_len); +hmac_ctx_reset (ctx); +hmac_ctx_reset (ctx_tmp); +hmac_ctx_update (ctx,A1 ,A1_len); +hmac_ctx_update (ctx_tmp,A1 ,A1_len); +hmac_ctx_update (ctx,seed,seed_len);if (olen > chunk) { -hmac_ctx_final (&ctx, out); +hmac_ctx_final (ctx, out); out += chunk; olen -= chunk; -hmac_ctx_final (&ctx_tmp,A1 );/* calc the next A1 value */ +hmac_ctx_final (ctx_tmp,A1 );/* calc the next A1 value */ }else /* last one */ { -hmac_ctx_final (&ctx,A1 ); +hmac_ctx_final (ctx,A1 );memcpy (out,A1 ,olen);break ; } } -hmac_ctx_cleanup (&ctx); -hmac_ctx_cleanup (&ctx_tmp); +hmac_ctx_cleanup (ctx); +hmac_ctx_free (ctx); +hmac_ctx_cleanup (ctx_tmp); +hmac_ctx_free (ctx_tmp);secure_memzero (A1 ,sizeof (A1 ));dmsg (D_SHOW_KEY_SOURCE ,"tls1_P_hash out: %s" ,format_hex (out_orig, olen_orig,0 , &gc));
Signature · 1 line
2.7.4
RFC PATCH 13/15 OpenSSL: SSLeay symbols are no longer available in OpenSSL 1.1
In reply to [email protected]...From: Emmanuel Deloget <[email protected]...>
The old symbols do not exist anymore but the library gained new equivalent symbols (OSSL). Use them instead of the old ones
--- src/openvpn/openssl_compat.h | 5 +++++ src/openvpn/ssl_openssl.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-)
src/openvpn/openssl_compat.h +5 -0
@@ -601,4 +601,9 @@ RSA_meth_set0_app_data(RSA_METHOD *meth, void *app_data) }#endif +/* SSLeay symbols have been renamed in OpenSSL 1.1 */ +#if !defined(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT ) +#define RSA_F_RSA_OSSL_PRIVATE_ENCRYPT RSA_F_RSA_EAY_PRIVATE_ENCRYPT +#endif +#endif /* OPENSSL_COMPAT_H_ */
src/openvpn/ssl_openssl.c +1 -1
@@ -996,7 +996,7 @@ rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, iif (padding !=RSA_PKCS1_PADDING ) { -RSAerr (RSA_F_RSA_EAY_PRIVATE_ENCRYPT ,RSA_R_UNKNOWN_PADDING_TYPE ); +RSAerr (RSA_F_RSA_OSSL_PRIVATE_ENCRYPT ,RSA_R_UNKNOWN_PADDING_TYPE ); goto done; }
Signature · 1 line
2.7.4
Re: [Openvpn-devel] [RFC PATCH v1 13/15] OpenSSL: SSLeay symbols are no longer available in OpenSSL 1.1
Hi,
Quoted 31 lines · On 17-02-17 23:00, [email protected]... wrote:
From: Emmanuel Deloget <[email protected]...>
The old symbols do not exist anymore but the library gained new equivalent symbols (OSSL). Use them instead of the old ones
Signed-off-by Emmanuel Deloget <[email protected]...>--- src/openvpn/openssl_compat.h | 5 +++++ src/openvpn/ssl_openssl.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-)src/openvpn/openssl_compat.h +5
-0@@ -601,4 +601,9 @@ RSA_meth_set0_app_data(RSA_METHOD *meth, void *app_data) }#endif +/* SSLeay symbols have been renamed in OpenSSL 1.1 */ +#if !defined(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT ) +#define RSA_F_RSA_OSSL_PRIVATE_ENCRYPT RSA_F_RSA_EAY_PRIVATE_ENCRYPT +#endif +#endif /* OPENSSL_COMPAT_H_ */ src/openvpn/ssl_openssl.c +0
-0
src/openvpn/ssl_openssl.c rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, i · line 1002
Quoted 8 lines
src/openvpn/ssl_openssl.c +1
-1@@ -996,7 +996,7 @@ rsa_priv_enc(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, iif (padding !=RSA_PKCS1_PADDING ) { -RSAerr (RSA_F_RSA_EAY_PRIVATE_ENCRYPT ,RSA_R_UNKNOWN_PADDING_TYPE ); +RSAerr (RSA_F_RSA_OSSL_PRIVATE_ENCRYPT ,RSA_R_UNKNOWN_PADDING_TYPE ); goto done; }
ACK
-Steffan
[Openvpn-devel] [PATCH applied] Re: OpenSSL: SSLeay symbols are no longer available in OpenSSL 1.1
In reply to [email protected]...Your patch has been applied to the master and release/2.4 branch.
commit c828ffc648eebda20e2f9087248944fa0f52a582 (master) commit d702b2539d43a3326d76cc1764fedf237fc6744f (release/2.4)
Author: Emmanuel Deloget Date: Fri Feb 17 23:00:52 2017 +0100
OpenSSL: SSLeay symbols are no longer available in OpenSSL 1.1
Signed-off-by: Emmanuel Deloget <[email protected]...>
Acked-by: Steffan Karger <[email protected]...>
Message-Id: <9ce17efda7b1ed100e73554b1916c0bfa687d9d1.1487368114.git.logout@...260...>
URL: https://www.mail-archive.com/[email protected]/msg14089.html
Signed-off-by: Gert Doering <[email protected]...>--
kind regards,
Gert Doering
RFC PATCH 14/15 OpenSSL: check for the SSL reason, not the full error
In reply to [email protected]...From: Emmanuel Deloget <[email protected]...>
OpenSSL 1.1 changed the SSLv3 API and removed many SSL_L_SSL3_* constants. Moreover, new code might use different function code for the same error.
Thus, we extract the error reason from the error code before we compare it instead of trying to rebuild an error code that might not be correct.
The new version is compatible with OpenSSL 1.0.x as well as with older versions (starting at 0.9.8).
--- src/openvpn/crypto_openssl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
src/openvpn/crypto_openssl.c +1 -2
@@ -194,8 +194,7 @@ crypto_print_openssl_errors(const unsigned int flags)while ((err =ERR_get_error ())) {/* Be more clear about frequently occurring "no shared cipher" error */ -if (err ==ERR_PACK (ERR_LIB_SSL ,SSL_F_SSL3_GET_CLIENT_HELLO , -SSL_R_NO_SHARED_CIPHER )) +if (ERR_GET_REASON (err) ==SSL_R_NO_SHARED_CIPHER ) {msg (D_CRYPT_ERRORS ,"TLS error: The server has no TLS ciphersuites " "in common with the client. Your --tls-cipher setting might be "
Signature · 1 line
2.7.4
Re: [Openvpn-devel] [RFC PATCH v1 14/15] OpenSSL: check for the SSL reason, not the full error
Hi,
Quoted 24 lines · On 17-02-17 23:00, [email protected]... wrote:
From: Emmanuel Deloget <[email protected]...>
OpenSSL 1.1 changed the SSLv3 API and removed many SSL_L_SSL3_* constants. Moreover, new code might use different function code for the same error.
Thus, we extract the error reason from the error code before we compare it instead of trying to rebuild an error code that might not be correct.
The new version is compatible with OpenSSL 1.0.x as well as with older versions (starting at 0.9.8).
Signed-off-by Emmanuel Deloget <[email protected]...>--- src/openvpn/crypto_openssl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)src/openvpn/crypto_openssl.c +0
-0
src/openvpn/crypto_openssl.c crypto_print_openssl_errors(const unsigned int flags) · line 200
Quoted 9 lines
src/openvpn/crypto_openssl.c +1
-2@@ -194,8 +194,7 @@ crypto_print_openssl_errors(const unsigned int flags)while ((err =ERR_get_error ())) {/* Be more clear about frequently occurring "no shared cipher" error */ -if (err ==ERR_PACK (ERR_LIB_SSL ,SSL_F_SSL3_GET_CLIENT_HELLO , -SSL_R_NO_SHARED_CIPHER )) +if (ERR_GET_REASON (err) ==SSL_R_NO_SHARED_CIPHER ) {msg (D_CRYPT_ERRORS ,"TLS error: The server has no TLS ciphersuites " "in common with the client. Your --tls-cipher setting might be "
This patch is correct even outside the context of the transition to 1.1, and can be applied immediately. ACK.
-Steffan
[Openvpn-devel] [PATCH applied] Re: OpenSSL: check for the SSL reason, not the full error
In reply to [email protected]...Your patch has been applied to the master and release/2.4 branch.
2.3 does not have this code, as far as I could see, so doesn't get the patch.
I can't reach sf.net right now (git.code.sf.net gives me "connection refused"), so only pushed to github and gitlab.
commit 6ddc43d1bf9b3ea3ee5db8c50d56a98fe4db4c97 (master) commit c4c359736e3ab7f06a21f1eab09e6fd4cf2bef2f (release/2.4)
Author: Emmanuel Deloget Date: Fri Feb 17 23:00:53 2017 +0100
OpenSSL: check for the SSL reason, not the full error
Signed-off-by: Emmanuel Deloget <[email protected]...>
Acked-by: Steffan Karger <[email protected]...>
Message-Id: <0e0d4a67192b563cd07d3f06685f85e34c304142.1487368114.git.logout@...260...>
URL: https://www.mail-archive.com/[email protected]/msg14087.html
Signed-off-by: Gert Doering <[email protected]...>--
kind regards,
Gert Doering
RFC PATCH 15/15 OpenSSL: constify getbio() parameters
In reply to [email protected]...From: Emmanuel Deloget <[email protected]...>
Although it is required by BIO_new() to have a non-const object, this is merely an OpenSSL interface accident. Newer versions of OpenSSL (i.e. OpenSSL 1.1) have are a bit better w.r.t. constification and changed this.
As a result, we can safely constify the BIO_METHOD parameter of getbio() (yet we still need to un-const the value when feeding it to BIO_new() for the sake of compatibility).
--- src/openvpn/ssl_openssl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
src/openvpn/ssl_openssl.c +2 -2
@@ -1389,10 +1389,10 @@ bio_debug_oc(const char *mode, BIO *bio)* through "memory BIOs". */ static BIO * -getbio (BIO_METHOD *type,const char *desc) +getbio (const BIO_METHOD *type,const char *desc) {BIO *ret; - ret =BIO_new (type); + ret =BIO_new ((BIO_METHOD *)type);if (!ret) {crypto_msg (M_FATAL ,"Error creating %s BIO" , desc);
Signature · 1 line
2.7.4
Hi Emmanuel,
Quoted 56 lines · On 17-02-17 23:00, [email protected]... wrote:
From: Emmanuel Deloget <[email protected]...>
The purpose of this RFC series is to make the latest master of OpenVPN (2.5-git) linkable with OpenSSL v1.1.x. It may not be complete (I may have missed something due to my work environment, but any missing pieces will be added next week) so be a bit cautious with this. The configuration I used (--without-systemd, --without-lzo) seems to work but I must confess I did not tested much.
As you may know, the important information about the API of OpenSSL 1.1 if that it no longer provide access to the content of its objects. The structure types are now opaque and various functions have been added to fetch information from these objects.
Once theses patches have been applied, it is possible to compile OpenSSL with the latest 1.0.1 and with the latest 1.1.0. I still have to check whether compilation with 1.0.0 and 0.9.8 works. I don't try to get the OpenSSL version -- I instead decided to check for the presence of individual functions in the library and chose to reimplement the missing ones. Then I changed caller code in order to use this new interface. The net result is that OpenVPN is now using the OpenSSL 1.1 API -- regardless of the real version of OpenSSL. This might make futur changes simpler at the cost of adding more functions in the
openssl_compat.hfile.Las but not least, because of the way I worked I introduced some strange artefacts (I believe they are not really relevant but some of them are weird enough to need some explaination).
* I had to introduce a function of the 1.0 API in the 1.1 code. In the 1.0 API,
HMAC_CTXis populated withHMAC_CTX_init()and cleaned withHMAC_CTX_cleanup(). In 1.1 these two functions are gone and replaced withHMAC_CTX_reset(). I decided to use_reset()to implement_cleanup()but since I then could not use it for_init()(that would break an OpenVPN linked with 1.0) I created a small wrapper in 1.1 mode. So, in 1.1,HMAC_CTX_init()calls_reset()-- and everybody is happy (well, maybe not everybody).*
HMAC_CTX,EVP_MD_CTXand a few other objects cannot be allocated usingmalloc()so I had to change the way these object are used and initialized. I introduces a few new functions in the crypto backend to handle this.*
x509_verify_ns_cert_type()checks had to be changed. OpenSSL 1.1 does not provide any solution to access bothX509::ex_flagsandX509::ex_nscertso the check could not be implemented this way. The only solution I found was to useX509_check_purpose()but I'm worried that the implemented test is now far more strict.* weirdly enough, it's no longer possible to duplicate the n parameter of a RSA public key into another RSA public key. If you do so, you also need to duplicate the e parameter. The reason is that you cannot have (n && !e) or (!n && e) (see RSA_set0_key[1]). I deciced to go the same route in my implementation and thus I needed to change the code in
tls_ctx_use_external_private_key().
Quoted 5 lines
Thanks for your comprehension,
[1] https://github.com/openssl/openssl/blob/master/crypto/rsa/rsa_lib.c#L191
-- Emmanuel Deloget
Thank you very much. You approach looks good to me, and quite closely matches what I had in mind for when I would find the time to tackle this. (Which might have taken me a while, so really happy to see these patches!)
As discussed in other threads, we do want to support building on RHEL6, which is why we would prefer to be compatible with (patched) OpenSSL 0.9.8. I haven't tested anything yet, but looking at the patches this might very well just work, or otherwise just needs some minor tweaking.
Also very good that this is split up into small and independently reviewable patches. I'll start review soon.
-Steffan
Quoted 4 lines · Steffan Karger
As discussed in other threads, we do want to support building on RHEL6, which is why we would prefer to be compatible with (patched) OpenSSL 0.9.8. I haven't tested anything yet, but looking at the patches this might very well just work, or otherwise just needs some minor tweaking.
RHEL6 ships with OpenSSL 1.0.1e. We don't need anything older for git master, and I would even argue release/2.4.
RHEL5 (which goes EOL by end of next month) ships with OpenSSL 0.9.8e. So I vote for ditching 0.9.8e now.
Signature · 4 lines
kind regards, David Sommerseth OpenVPN Technologies, Inc
Quoted 7 lines · David Sommerseth
Quoted 4 lines · Steffan Karger
As discussed in other threads, we do want to support building on RHEL6, which is why we would prefer to be compatible with (patched) OpenSSL 0.9.8. I haven't tested anything yet, but looking at the patches this might very well just work, or otherwise just needs some minor tweaking.
Quoted 5 lines
RHEL6 ships with OpenSSL 1.0.1e. We don't need anything older for git master, and I would even argue release/2.4.
RHEL5 (which goes EOL by end of next month) ships with OpenSSL 0.9.8e. So I vote for ditching 0.9.8e now.
Oh, very good. I messed up the versions again...
The other big long-term-support distro, SLES, does still ship and support 0.9.8 in SELS11 until 2019 (2022 for extended support), but can be updated to 1.0.1.
As far as I'm concerned, that is enough reason to only support OpenSSL 1.0.1+ for OpenVPN 2.4 (and newer).
-Steffan
Hello,
Quoted 8 lines · Steffan Karger
Hi Emmanuel,
Thank you very much. You approach looks good to me, and quite closely matches what I had in mind for when I would find the time to tackle this. (Which might have taken me a while, so really happy to see these patches!)
Thanks Steffan,
Quoted 4 lines
As discussed in other threads, we do want to support building on RHEL6, which is why we would prefer to be compatible with (patched) OpenSSL 0.9.8. I haven't tested anything yet, but looking at the patches this might very well just work, or otherwise just needs some minor tweaking.
I haven't tested compilation with 0.9.8 but unless some massive changes in the interface occured, this should not be a problem. I'd do that at the beginning of next week.
Quoted 4 lines
Also very good that this is split up into small and independently reviewable patches. I'll start review soon.
-Steffan
For the record, most of the patches deal with changing how the code access to one selected OpenSSL type. I hope it will ease review -- in the sense that people who are accustomed to the code might be able to see if something is missing.
BR,
-- Emmanuel Deloget
Hi,
Quoted 4 lines · Steffan Karger
Thank you very much. You approach looks good to me, and quite closely matches what I had in mind for when I would find the time to tackle this. (Which might have taken me a while, so really happy to see these patches!)
[..]
Quoted 2 lines
Also very good that this is split up into small and independently reviewable patches. I'll start review soon.
While Steffan is our resident expert on nasty crypto libraries, I just want to echo the sentiment - having these "chunks" tackle one API function at a time, they are easily testable, and in case something explodes, it's much easier to bisect to find the problematic one.
Now back to being a commit slave for Steffan's ACKs :-) (I do not know the APIs well enough to properly comment on the changes, I can only run tests...)
gert
Signature · 4 lines
USENET is *not* the non-clickable part of WWW!
//www.muc.de/~gert/
Gert Doering - Munich, Germany [email protected]...
fax: +49-89-35655025 [email protected]...Hello,
Quoted 11 lines · Gert Doering
Hi,
Quoted 4 lines · Steffan Karger
Thank you very much. You approach looks good to me, and quite closely matches what I had in mind for when I would find the time to tackle this. (Which might have taken me a while, so really happy to see these patches!)
[..]
Quoted 2 lines
Also very good that this is split up into small and independently reviewable patches. I'll start review soon.
Quoted 8 lines
While Steffan is our resident expert on nasty crypto libraries, I just want to echo the sentiment - having these "chunks" tackle one API function at a time, they are easily testable, and in case something explodes, it's much easier to bisect to find the problematic one.
Now back to being a commit slave for Steffan's ACKs :-) (I do not know the APIs well enough to properly comment on the changes, I can only run tests...)
I resumed the work this morning. So far the results are :
* 0.9.8zh --> EVP_PKEY_id() is not defined. I'm adding this to openssl_compat.h and will provide a v2 patch with the change. Once added, OpenVPN compiled successfully and was able to connect to my /2.3 server.
* 1.0.0t --> compile OK, connect OK
* 1.0.1u --> compile OK, connect OK
* 1.0.2.k --> compile OK, connect OK
* 1.1.0-git --> compile OK, failure to connect. I'm currently investigating this issue. I'll provide a patch as soon as I fix this (this is a bit ironic ; I may have forgotten something somewhere...).
I don't have much time to test with other OpenSSL versions but I guess you have the infrastructure that will help.
Quoted 1 line
gert
Best regards,
-- Emmanuel Deloget
Emmanuel Deloget <[email protected]...> on Mon, 2017/02/20 12:45:
Quoted 32 lines
Hello,
Quoted 11 lines · Gert Doering
Hi,
Quoted 4 lines · Steffan Karger
Thank you very much. You approach looks good to me, and quite closely matches what I had in mind for when I would find the time to tackle this. (Which might have taken me a while, so really happy to see these patches!)
[..]
Quoted 2 lines
Also very good that this is split up into small and independently reviewable patches. I'll start review soon.
Quoted 8 lines
While Steffan is our resident expert on nasty crypto libraries, I just want to echo the sentiment - having these "chunks" tackle one API function at a time, they are easily testable, and in case something explodes, it's much easier to bisect to find the problematic one.
Now back to being a commit slave for Steffan's ACKs :-) (I do not know the APIs well enough to properly comment on the changes, I can only run tests...)
I resumed the work this morning. So far the results are :
* 0.9.8zh -->
EVP_PKEY_id()is not defined. I'm adding this toopenssl_compat.hand will provide a v2 patch with the change. Once added, OpenVPN compiled successfully and was able to connect to my /2.3 server.* 1.0.0t --> compile OK, connect OK
Quoted 7 lines
* 1.0.1u --> compile OK, connect OK
* 1.0.2.k --> compile OK, connect OK
* 1.1.0-git --> compile OK, failure to connect. I'm currently investigating this issue. I'll provide a patch as soon as I fix this (this is a bit ironic ; I may have forgotten something somewhere...).
That matches my findings. Built against openssl 1.1.0e (Arch Linux package openssl 1.1.0.e-1 [0]) the build itself succeeds, but 'make check' reports lots of cipher failures.
Are your patches available from a public git repository?
[0] https://www.archlinux.org/packages/staging/x86_64/openssl/
Signature · 3 lines
main(a){char*c=/* Schoene Gruesse */"B?IJj;MEH"
"CX:;",b;for(a/* Best regards my address: */=0;b=c[a++];)
putchar(b-1/(/* Chris cc -ox -xc - && ./x */b/42*2-3)*42);}Hi Christian,
Quoted 5 lines · Christian Hesse
That matches my findings. Built against openssl 1.1.0e (Arch Linux package openssl 1.1.0.e-1 [0]) the build itself succeeds, but 'make check' reports lots of cipher failures.
Are your patches available from a public git repository?
I will make my patches available on github ASAP.
Best regards
-- Emmanuel Deloget
Quoted 52 lines · Christian Hesse
Emmanuel Deloget <[email protected]...> on Mon, 2017/02/20 12:45:
Quoted 32 lines
Hello,
Quoted 11 lines · Gert Doering
Hi,
Quoted 4 lines · Steffan Karger
Thank you very much. You approach looks good to me, and quite closely matches what I had in mind for when I would find the time to tackle this. (Which might have taken me a while, so really happy to see these patches!)
[..]
Quoted 2 lines
Also very good that this is split up into small and independently reviewable patches. I'll start review soon.
Quoted 8 lines
While Steffan is our resident expert on nasty crypto libraries, I just want to echo the sentiment - having these "chunks" tackle one API function at a time, they are easily testable, and in case something explodes, it's much easier to bisect to find the problematic one.
Now back to being a commit slave for Steffan's ACKs :-) (I do not know the APIs well enough to properly comment on the changes, I can only run tests...)
I resumed the work this morning. So far the results are :
* 0.9.8zh -->
EVP_PKEY_id()is not defined. I'm adding this toopenssl_compat.hand will provide a v2 patch with the change. Once added, OpenVPN compiled successfully and was able to connect to my /2.3 server.* 1.0.0t --> compile OK, connect OK
Quoted 7 lines
* 1.0.1u --> compile OK, connect OK
* 1.0.2.k --> compile OK, connect OK
* 1.1.0-git --> compile OK, failure to connect. I'm currently investigating this issue. I'll provide a patch as soon as I fix this (this is a bit ironic ; I may have forgotten something somewhere...).
That matches my findings. Built against openssl 1.1.0e (Arch Linux package openssl 1.1.0.e-1 [0]) the build itself succeeds, but 'make check' reports lots of cipher failures.
Are your patches available from a public git repository?
[0] https://www.archlinux.org/packages/staging/x86_64/openssl/
--
main(a){char*c=/* Schoene Gruesse */"B?IJj;MEH"
"CX:;",b;for(a/* Best regards my address: */=0;b=c[a++];)putchar(b-1/(/* Chris cc -ox -xc - && ./x */b/42*2-3)*42);}
Hi again,
Quoted 10 lines · Emmanuel Deloget
Hi Christian,
Quoted 5 lines · Christian Hesse
That matches my findings. Built against openssl 1.1.0e (Arch Linux package openssl 1.1.0.e-1 [0]) the build itself succeeds, but 'make check' reports lots of cipher failures.
Are your patches available from a public git repository?
I will make my patches available on github ASAP.
I did as fast as I could, here they are:
https://github.com/emmanuel-deloget/openvpn/commits/openvpn-1.1
I post the PATCH V2 in a few minutes
-- Emmanuel Deloget
Quoted 10 lines · Emmanuel Deloget
Hi again,
Quoted 7 lines · Emmanuel Deloget
Hi Christian,
Quoted 4 lines · Christian Hesse
That matches my findings. Built against openssl 1.1.0e (Arch Linux package openssl 1.1.0.e-1 [0]) the build itself succeeds, but 'make check' reports lots of cipher failures.
Quoted 7 lines
Quoted 3 lines
Quoted 1 line
Are your patches available from a public git repository?
I will make my patches available on github ASAP.
I did as fast as I could, here they are:
https://github.com/emmanuel-deloget/openvpn/commits/openvpn-1.1
BTW, sorry for the branch name. I believe my fingers got stuck to a limited number of characters. This should have been openssl-1.1 but it's not too late to change it :)
Emmanuel Deloget <[email protected]...> on Mon, 2017/02/20 15:52:
Quoted 16 lines · Emmanuel Deloget
Quoted 15 lines
Hi again,
Quoted 10 lines · Emmanuel Deloget
Hi Christian,
Quoted 5 lines · Christian Hesse
That matches my findings. Built against openssl 1.1.0e (Arch Linux package openssl 1.1.0.e-1 [0]) the build itself succeeds, but 'make check' reports lots of cipher failures.
Are your patches available from a public git repository?
I will make my patches available on github ASAP.
Quoted 7 lines
Quoted 3 lines
I did as fast as I could, here they are:
https://github.com/emmanuel-deloget/openvpn/commits/openvpn-1.1
BTW, sorry for the branch name. I believe my fingers got stuck to a limited number of characters. This should have been openssl-1.1 but it's not too late to change it :)
Ah, I checked out the wrong branch. :-p
Redoing my test...
Signature · 3 lines
main(a){char*c=/* Schoene Gruesse */"B?IJj;MEH"
"CX:;",b;for(a/* Best regards my address: */=0;b=c[a++];)
putchar(b-1/(/* Chris cc -ox -xc - && ./x */b/42*2-3)*42);}Christian Hesse <[email protected]...> on Mon, 2017/02/20 16:02:
Quoted 23 lines
Emmanuel Deloget <[email protected]...> on Mon, 2017/02/20 15:52:
Quoted 22 lines
Quoted 19 lines · Emmanuel Deloget
Hi again,
Quoted 11 lines · Emmanuel Deloget
Hi Christian,
Quoted 5 lines · Christian Hesse
That matches my findings. Built against openssl 1.1.0e (Arch Linux package openssl 1.1.0.e-1 [0]) the build itself succeeds, but 'make check' reports lots of cipher failures.
Are your patches available from a public git repository?
I will make my patches available on github ASAP.
I did as fast as I could, here they are:
https://github.com/emmanuel-deloget/openvpn/commits/openvpn-1.1
Quoted 7 lines
Quoted 3 lines
BTW, sorry for the branch name. I believe my fingers got stuck to a limited number of characters. This should have been openssl-1.1 but it's not too late to change it :)
Ah, I checked out the wrong branch. :-p
Redoing my test...
That one looks good! Build and tested against ArchLinux package openssl 1.1.0e.
Signature · 3 lines
main(a){char*c=/* Schoene Gruesse */"B?IJj;MEH"
"CX:;",b;for(a/* Best regards my address: */=0;b=c[a++];)
putchar(b-1/(/* Chris cc -ox -xc - && ./x */b/42*2-3)*42);}v3 cover Add support for OpenSSL 1.1.x
This is v3 of the remaining patches for the "Add support for OpenSSL 1.1.x" series. This series is partial: only the modified patches are sent to the ML -- the other have not changed. The stats are a bit off so I don't include them in this mail.
They have been generated after a rebase from the master tree. Individual commits can be viewed at
https://github.com/emmanuel-deloget/openvpn/commits/openssl-1.1-v3
(This time, the branch name is correct :))
Changes v2 --> v3:
* RSA_METHOD (04/15): rsa_meth->name is now a dup of the name parameter; it's freed in RSA_meth_free().
* RSA (07/15): calling RSA_set_method() in rsa_finish() is both a Bad Idea and not required so it has been removed.
Changes v1 --> v2:
* EVP_PKEY (06/15): add missing function EVP_PKEY_id() for 0.9.8.
* replace patch 15/15 with a new patch to use EVP_CipherInit_ex() instead of EVP_CipherInit() when a full init is not needed.
Emmanuel Deloget (15):
[commited] OpenSSL: don't use direct access to the internal of SSL_CTX [commited] OpenSSL: don't use direct access to the internal of X509_STORE [commited] OpenSSL: don't use direct access to the internal of X509_OBJECT
OpenSSL: don't use direct access to the internal of RSA_METHOD
OpenSSL: don't use direct access to the internal of X509
OpenSSL: don't use direct access to the internal of EVP_PKEY
OpenSSL: don't use direct access to the internal of RSA
OpenSSL: don't use direct access to the internal of DSA [commited] OpenSSL: don't use direct access to the internal of X509_STORE_CTX
OpenSSL: don't use direct access to the internal of EVP_MD_CTX
OpenSSL: don't use direct access to the internal of EVP_CIPHER_CTX
OpenSSL: don't use direct access to the internal of HMAC_CTX
OpenSSL: SSLeay symbols are no longer available in OpenSSL 1.1
OpenSSL: constify getbio() parameters
OpenSSL: use EVP_CipherInit_ex() instead of EVP_CipherInit()
Signature · 1 line
2.7.4
PATCH v3 4/15 OpenSSL: don't use direct access to the internal of RSA_METHOD
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including RSA_METHOD. We have to use the defined functions to do so.
Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
--- configure.ac | 9 ++ src/openvpn/openssl_compat.h | 190 +++++++++++++++++++++++++++++++++++++++++++ src/openvpn/ssl_openssl.c | 22 ++--- 3 files changed, 210 insertions(+), 11 deletions(-)
configure.ac +9 -0
@@ -905,6 +905,15 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then X509_STORE_get0_objects \ X509_OBJECT_free \ X509_OBJECT_get_type \ + RSA_meth_new \ + RSA_meth_free \ + RSA_meth_set_pub_enc \ + RSA_meth_set_pub_dec \ + RSA_meth_set_priv_enc \ + RSA_meth_set_priv_dec \ + RSA_meth_set_init \ + RSA_meth_set_finish \ + RSA_meth_set0_app_data \ ] )
src/openvpn/openssl_compat.h +190 -0
200 lines not on this page · raw message
src/openvpn/ssl_openssl.c +11 -11
@@ -978,7 +978,7 @@ rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, istatic int rsa_finish (RSA *rsa) { -free ((void *)rsa->meth); +RSA_meth_free (rsa->meth); rsa->meth =NULL ;return 1 ; }
@@ -1053,16 +1053,16 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx,ASSERT (NULL != cert);/* allocate custom RSA method object */ -ALLOC_OBJ_CLEAR (rsa_meth,RSA_METHOD ); - rsa_meth->name ="OpenVPN external private key RSA Method" ; - rsa_meth->rsa_pub_enc = rsa_pub_enc; - rsa_meth->rsa_pub_dec = rsa_pub_dec; - rsa_meth->rsa_priv_enc = rsa_priv_enc; - rsa_meth->rsa_priv_dec = rsa_priv_dec; - rsa_meth->init =NULL ; - rsa_meth->finish = rsa_finish; - rsa_meth->flags =RSA_METHOD_FLAG_NO_CHECK ; - rsa_meth->app_data =NULL ; + rsa_meth =RSA_meth_new ("OpenVPN external private key RSA Method" , +RSA_METHOD_FLAG_NO_CHECK ); +check_malloc_return (rsa_meth); +RSA_meth_set_pub_enc (rsa_meth, rsa_pub_enc); +RSA_meth_set_pub_dec (rsa_meth, rsa_pub_dec); +RSA_meth_set_priv_enc (rsa_meth, rsa_priv_enc); +RSA_meth_set_priv_dec (rsa_meth, rsa_priv_dec); +RSA_meth_set_init (rsa_meth,NULL ); +RSA_meth_set_finish (rsa_meth, rsa_finish); +RSA_meth_set0_app_data (rsa_meth,NULL );/* allocate RSA object */ rsa =RSA_new ();
Signature · 1 line
2.7.4
Re: [Openvpn-devel] [PATCH v3 04/15] OpenSSL: don't use direct access to the internal of RSA_METHOD
Hi,
Quoted 271 lines · Emmanuel Deloget
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including
RSA_METHOD. We have to use the defined functions to do so.Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
Signed-off-by Emmanuel Deloget <[email protected]...>--- configure.ac | 9 ++ src/openvpn/openssl_compat.h | 190 +++++++++++++++++++++++++++++++++++++++++++ src/openvpn/ssl_openssl.c | 22 ++--- 3 files changed, 210 insertions(+), 11 deletions(-)configure.ac +9
-0@@ -905,6 +905,15 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then X509_STORE_get0_objects \ X509_OBJECT_free \ X509_OBJECT_get_type \ + RSA_meth_new \ + RSA_meth_free \ + RSA_meth_set_pub_enc \ + RSA_meth_set_pub_dec \ + RSA_meth_set_priv_enc \ + RSA_meth_set_priv_dec \ + RSA_meth_set_init \ + RSA_meth_set_finish \ + RSA_meth_set0_app_data \ ] )src/openvpn/openssl_compat.h +190
-0@@ -41,6 +41,8 @@#include "config-msvc.h" #endif +#include "buffer.h" +#include <openssl/ssl.h> #include <openssl/x509.h> @@ -117,4 +119,192 @@ X509_OBJECT_get_type(const X509_OBJECT *obj) }#endif +#if !defined(HAVE_RSA_METH_NEW ) +/** +* Allocate a new RSA method object +* +* @param name The object name +* @param flags Configuration flags +* @return A new RSA method object +*/ +static inline RSA_METHOD * +RSA_meth_new (const char *name,int flags) +{ +RSA_METHOD *rsa_meth =NULL ; +ALLOC_OBJ_CLEAR (rsa_meth,RSA_METHOD ); + rsa_meth->name =string_alloc (name,NULL ); + rsa_meth->flags = flags; +return rsa_meth; +} +#endif + +#if !defined(HAVE_RSA_METH_FREE ) +/** +* Free an existing RSA_METHOD object +* +* @param meth The RSA_METHOD object +*/ +static inline void +RSA_meth_free (RSA_METHOD *meth) +{ +if (meth) + { +free (meth->name); +free (meth); + } +} +#endif + +#if !defined(HAVE_RSA_METH_SET_PUB_ENC ) +/** +* Set the public encoding function of an RSA_METHOD object +* +* @param meth The RSA_METHOD object +* @param pub_enc the public encoding function +* @return 1 on success, 0 on error +*/ +static inline int +RSA_meth_set_pub_enc (RSA_METHOD *meth, +int (*pub_enc) (int flen,const unsigned char *from, +unsigned char *to,RSA *rsa, +int padding)) +{ +if (meth) + { + meth->rsa_pub_enc = pub_enc; +return 1 ; + } +return 0 ; +} +#endif + +#if !defined(HAVE_RSA_METH_SET_PUB_DEC ) +/** +* Set the public decoding function of an RSA_METHOD object +* +* @param meth The RSA_METHOD object +* @param pub_dec the public decoding function +* @return 1 on success, 0 on error +*/ +static inline int +RSA_meth_set_pub_dec (RSA_METHOD *meth, +int (*pub_dec) (int flen,const unsigned char *from, +unsigned char *to,RSA *rsa, +int padding)) +{ +if (meth) + { + meth->rsa_pub_dec = pub_dec; +return 1 ; + } +return 0 ; +} +#endif + +#if !defined(HAVE_RSA_METH_SET_PRIV_ENC ) +/** +* Set the private encoding function of an RSA_METHOD object +* +* @param meth The RSA_METHOD object +* @param priv_enc the private encoding function +* @return 1 on success, 0 on error +*/ +static inline int +RSA_meth_set_priv_enc (RSA_METHOD *meth, +int (*priv_enc) (int flen,const unsigned char *from, +unsigned char *to,RSA *rsa, +int padding)) +{ +if (meth) + { + meth->rsa_priv_enc = priv_enc; +return 1 ; + } +return 0 ; +} +#endif + +#if !defined(HAVE_RSA_METH_SET_PRIV_DEC ) +/** +* Set the private decoding function of an RSA_METHOD object +* +* @param meth The RSA_METHOD object +* @param priv_dec the private decoding function +* @return 1 on success, 0 on error +*/ +static inline int +RSA_meth_set_priv_dec (RSA_METHOD *meth, +int (*priv_dec) (int flen,const unsigned char *from, +unsigned char *to,RSA *rsa, +int padding)) +{ +if (meth) + { + meth->rsa_priv_dec = priv_dec; +return 1 ; + } +return 0 ; +} +#endif + +#if !defined(HAVE_RSA_METH_SET_INIT ) +/** +* Set the init function of an RSA_METHOD object +* +* @param meth The RSA_METHOD object +* @param init the init function +* @return 1 on success, 0 on error +*/ +static inline int +RSA_meth_set_init (RSA_METHOD *meth,int (*init) (RSA *rsa)) +{ +if (meth) + { + meth->init = init; +return 1 ; + } +return 0 ; +} +#endif + +#if !defined(HAVE_RSA_METH_SET_FINISH ) +/** +* Set the finish function of an RSA_METHOD object +* +* @param meth The RSA_METHOD object +* @param finish the finish function +* @return 1 on success, 0 on error +*/ +static inline int +RSA_meth_set_finish (RSA_METHOD *meth,int (*finish) (RSA *rsa)) +{ +if (meth) + { + meth->finish = finish; +return 1 ; + } +return 0 ; +} +#endif + +#if !defined(HAVE_RSA_METH_SET0_APP_DATA ) +/** +* Set the application data of an RSA_METHOD object +* +* @param meth The RSA_METHOD object +* @param app_data Application data +* @return 1 on success, 0 on error +*/ +static inline int +RSA_meth_set0_app_data (RSA_METHOD *meth,void *app_data) +{ +if (meth) + { + meth->app_data = app_data; +return 1 ; + } +return 0 ; +} +#endif +#endif /* OPENSSL_COMPAT_H_ */ src/openvpn/ssl_openssl.c +4
-11@@ -978,7 +978,7 @@ rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, istatic int rsa_finish (RSA *rsa) { -free ((void *)rsa->meth); +RSA_meth_free (rsa->meth); rsa->meth =NULL ;return 1 ; }@@ -1053,16 +1053,16 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx,ASSERT (NULL != cert);/* allocate custom RSA method object */ -ALLOC_OBJ_CLEAR (rsa_meth,RSA_METHOD ); - rsa_meth->name ="OpenVPN external private key RSA Method" ; - rsa_meth->rsa_pub_enc = rsa_pub_enc; - rsa_meth->rsa_pub_dec = rsa_pub_dec; - rsa_meth->rsa_priv_enc = rsa_priv_enc; - rsa_meth->rsa_priv_dec = rsa_priv_dec; - rsa_meth->init =NULL ; - rsa_meth->finish = rsa_finish; - rsa_meth->flags =RSA_METHOD_FLAG_NO_CHECK ; - rsa_meth->app_data =NULL ; + rsa_meth =RSA_meth_new ("OpenVPN external private key RSA Method" , +RSA_METHOD_FLAG_NO_CHECK ); +check_malloc_return (rsa_meth);
src/openvpn/ssl_openssl.c tls_ctx_use_external_private_key(struct tls_root_ctx *ctx, · line 1068
Quoted 10 lines
src/openvpn/ssl_openssl.c +7
-0+RSA_meth_set_pub_enc (rsa_meth, rsa_pub_enc); +RSA_meth_set_pub_dec (rsa_meth, rsa_pub_dec); +RSA_meth_set_priv_enc (rsa_meth, rsa_priv_enc); +RSA_meth_set_priv_dec (rsa_meth, rsa_priv_dec); +RSA_meth_set_init (rsa_meth,NULL ); +RSA_meth_set_finish (rsa_meth, rsa_finish); +RSA_meth_set0_app_data (rsa_meth,NULL );/* allocate RSA object */ rsa =RSA_new ();
This looks good to me now, ACK. Thanks for following up.
-Steffan
[Openvpn-devel] [PATCH applied] Re: OpenSSL: don't use direct access to the internal of RSA_METHOD
In reply to Emmanuel DelogetYour patch (v3) has been applied to the master and release/2.4 branch.
Small side note: I assume that RSA_meth_new() can fail and return NULL in OpenSSL 1.1? Because for 1.0, the "check_malloc_return(rsa_meth)" call isn't necessary, as ALLOC_OBJ_CLEAR() would call ALLOC_OBJ() and that already checks... (mentioning this here in case someone wonders and goes to the list archives).
commit 09776c5b52df13121504e07894a26d5cd1883317 (master) commit 44bac2926d6b445a7773a24bb7c295b54f4be35e (release/2.4)
Author: Emmanuel Deloget Date: Thu Feb 23 15:35:56 2017 +0100
OpenSSL: don't use direct access to the internal of RSA_METHOD
Signed-off-by: Emmanuel Deloget <[email protected]...>
Acked-by: Steffan Karger <[email protected]...>
Message-Id: <79d89580db6fd92c059dabc4f5f4d83b72bb9d3d.1487859361.git.logout@...260...>
URL: https://www.mail-archive.com/[email protected]/msg14175.html
Signed-off-by: Gert Doering <[email protected]...>--
kind regards,
Gert Doering
Re: [Openvpn-devel] [PATCH applied] Re: OpenSSL: don't use direct access to the internal of RSA_METHOD
Quoted 5 lines · Gert Doering
Small side note: I assume that
RSA_meth_new()can fail and return NULL in OpenSSL 1.1? Because for 1.0, the "check_malloc_return(rsa_meth)" call isn't necessary, asALLOC_OBJ_CLEAR()would callALLOC_OBJ()and that already checks... (mentioning this here in case someone wonders and goes to the list archives).
For the archives: yes, RSA_meth_new() indeed returns NULL if it's internal malloc() call fails.
-Steffan
Re: [Openvpn-devel] [PATCH applied] Re: OpenSSL: don't use direct access to the internal of RSA_METHOD
Hi,
Quoted 10 lines · Steffan Karger
Quoted 5 lines · Gert Doering
Small side note: I assume that
RSA_meth_new()can fail and return NULL in OpenSSL 1.1? Because for 1.0, the "check_malloc_return(rsa_meth)" call isn't necessary, asALLOC_OBJ_CLEAR()would callALLOC_OBJ()and that already checks... (mentioning this here in case someone wonders and goes to the list archives).For the archives: yes,
RSA_meth_new()indeed returns NULL if it's internalmalloc()call fails.
Yes, indeed. And that's the reason why I have a check_malloc_return() here. I'm perfectly conscious that for OpenSSL < 1.1 we're checking the pointer twice but on the other hand I would have missed the check with OpenSSL 1.1. A solution would have been to use a direct malloc()/calloc() call instead of ALLOC_OBJ_CLEAR() in the compatibility code, but that would have looked weird. Another solution would have been to encapsulate RSA_meth_new() but I don't think that would have been a good idea (yet, I might be wrong on that one). So I did this choice -- I don't like it much either but I cannot think of a better solution.
Quoted 1 line
-Steffan
Best regards,
-- Emmanuel Deloget
Re: [Openvpn-devel] [PATCH applied] Re: OpenSSL: don't use direct access to the internal of RSA_METHOD
Hi,
Quoted 1 line · Emmanuel Deloget
I don't like it much either but I cannot think of a better solution.
I haven't said that I don't *like* it :-) - I came across it when doing a "post commit sanity check" and assumed that there are good reasons. Just wanted to clarify this, in case someone else looks at the call chain and wonders.
All is well :-)
gert
Signature · 4 lines
USENET is *not* the non-clickable part of WWW!
//www.muc.de/~gert/
Gert Doering - Munich, Germany [email protected]...
fax: +49-89-35655025 [email protected]...PATCH v3 7/15 OpenSSL: don't use direct access to the internal of RSA
In reply to Emmanuel DelogetOpenSSL 1.1 does not allow us to directly access the internal of any data type, including RSA. We have to use the defined functions to do so.
Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
--- configure.ac | 3 ++ src/openvpn/openssl_compat.h | 84 ++++++++++++++++++++++++++++++++++++++++++++ src/openvpn/ssl_openssl.c | 24 ++++++++----- 3 files changed, 103 insertions(+), 8 deletions(-)
configure.ac +3 -0
@@ -909,6 +909,9 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then EVP_PKEY_id \ EVP_PKEY_get0_RSA \ EVP_PKEY_get0_DSA \ + RSA_set_flags \ + RSA_get0_key \ + RSA_set0_key \ RSA_meth_new \ RSA_meth_free \ RSA_meth_set_pub_enc \
src/openvpn/openssl_compat.h +84 -0
90 lines not on this page · raw message
src/openvpn/ssl_openssl.c +16 -8
@@ -978,8 +978,8 @@ rsa_priv_dec(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, istatic int rsa_finish (RSA *rsa) { -RSA_meth_free (rsa->meth); - rsa->meth =NULL ; +const RSA_METHOD *meth =RSA_get_method (rsa); +RSA_meth_free ((RSA_METHOD *)meth);return 1 ; }
@@ -1078,8 +1078,11 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx, pub_rsa =EVP_PKEY_get0_RSA (pkey);/* initialize RSA object */ - rsa->n =BN_dup (pub_rsa->n); - rsa->flags |=RSA_FLAG_EXT_PKEY ; +const BIGNUM *n =NULL ; +const BIGNUM *e =NULL ; +RSA_get0_key (pub_rsa, &n, &e,NULL ); +RSA_set0_key (rsa,BN_dup (n),BN_dup (e),NULL ); +RSA_set_flags (rsa,RSA_flags (rsa) |RSA_FLAG_EXT_PKEY );if (!RSA_set_method (rsa, rsa_meth)) { goto err;
@@ -1680,11 +1683,16 @@ print_details(struct key_state_ssl *ks_ssl, const char *prefix)EVP_PKEY *pkey =X509_get_pubkey (cert);if (pkey !=NULL ) { -if (EVP_PKEY_id (pkey) ==EVP_PKEY_RSA &&EVP_PKEY_get0_RSA (pkey) !=NULL - && pkey->pkey.rsa->n !=NULL ) +if (EVP_PKEY_id (pkey) ==EVP_PKEY_RSA &&EVP_PKEY_get0_RSA (pkey) !=NULL ) { -openvpn_snprintf (s2,sizeof (s2),", %d bit RSA" , -BN_num_bits (pkey->pkey.rsa->n)); +RSA *rsa =EVP_PKEY_get0_RSA (pkey); +const BIGNUM *n =NULL ; +RSA_get0_key (rsa, &n,NULL ,NULL ); +if (n !=NULL ) + { +openvpn_snprintf (s2,sizeof (s2),", %d bit RSA" , +BN_num_bits (n)); + } }else if (EVP_PKEY_id (pkey) ==EVP_PKEY_DSA &&EVP_PKEY_get0_DSA (pkey) !=NULL && pkey->pkey.dsa->p !=NULL )
Signature · 1 line
2.7.4
Emmanuel Deloget <[email protected]...> on Thu, 2017/02/23 15:35:
Quoted 28 lines
This is v3 of the remaining patches for the "Add support for OpenSSL 1.1.x" series. This series is partial: only the modified patches are sent to the ML -- the other have not changed. The stats are a bit off so I don't include them in this mail.
They have been generated after a rebase from the master tree. Individual commits can be viewed at
https://github.com/emmanuel-deloget/openvpn/commits/openssl-1.1-v3
(This time, the branch name is correct :))
Changes v2 --> v3:
*
RSA_METHOD(04/15):rsa_meth->nameis now a dup of the name parameter; it's freed inRSA_meth_free().* RSA (07/15): calling
RSA_set_method()inrsa_finish()is both a Bad Idea and not required so it has been removed.Changes v1 --> v2:
*
EVP_PKEY(06/15): add missing functionEVP_PKEY_id()for 0.9.8.* replace patch 15/15 with a new patch to use
EVP_CipherInit_ex()instead ofEVP_CipherInit()when a full init is not needed.
Quoted 16 lines
Emmanuel Deloget (15):
[commited] OpenSSL: don't use direct access to the internal ofSSL_CTX[commited] OpenSSL: don't use direct access to the internal ofX509_STORE[commited] OpenSSL: don't use direct access to the internal ofX509_OBJECT
OpenSSL: don't use direct access to the internal ofRSA_METHOD
OpenSSL: don't use direct access to the internal of X509
OpenSSL: don't use direct access to the internal ofEVP_PKEY
OpenSSL: don't use direct access to the internal of RSA
OpenSSL: don't use direct access to the internal of DSA [commited] OpenSSL: don't use direct access to the internal ofX509_STORE_CTXOpenSSL: don't use direct access to the internal ofEVP_MD_CTXOpenSSL: don't use direct access to the internal ofEVP_CIPHER_CTXOpenSSL: don't use direct access to the internal ofHMAC_CTX
OpenSSL: SSLeay symbols are no longer available in OpenSSL 1.1
OpenSSL: constifygetbio()parameters
OpenSSL: useEVP_CipherInit_ex()instead ofEVP_CipherInit()
Built v3 against openssl 1.0.2k without issues, tests succeed and two instanced successfully established vpn connection (with server version 2.3.12 and 2.4.0).
Built against openssl 1.1.0e without issues, tests succeed. Did not test with real world connectivity, though.
Signature · 3 lines
main(a){char*c=/* Schoene Gruesse */"B?IJj;MEH"
"CX:;",b;for(a/* Best regards my address: */=0;b=c[a++];)
putchar(b-1/(/* Chris cc -ox -xc - && ./x */b/42*2-3)*42);}Christian Hesse <[email protected]...> on Thu, 2017/02/23 21:57:
Quoted 3 lines
Built v3 against openssl 1.0.2k without issues, tests succeed and two instanced successfully established vpn connection (with server version 2.3.12 and 2.4.0).
Just tested a server instance with ancient client (version 2.1.4). Works as well.
I will try to restart another server instance later.
Signature · 3 lines
main(a){char*c=/* Schoene Gruesse */"B?IJj;MEH"
"CX:;",b;for(a/* Best regards my address: */=0;b=c[a++];)
putchar(b-1/(/* Chris cc -ox -xc - && ./x */b/42*2-3)*42);}Christian Hesse <[email protected]...> on Fri, 2017/02/24 13:13:
Quoted 9 lines
Christian Hesse <[email protected]...> on Thu, 2017/02/23 21:57:
Quoted 3 lines
Built v3 against openssl 1.0.2k without issues, tests succeed and two instanced successfully established vpn connection (with server version 2.3.12 and 2.4.0).
Just tested a server instance with ancient client (version 2.1.4). Works as well.
I will try to restart another server instance later.
Just restarted the server. Here is the current client connect statistic:
1 2.3.8
4 2.3.12
6 2.3.13
7 2.3.11
18 2.3.14
70 2.4.0So looks good for now. ;)
Signature · 3 lines
main(a){char*c=/* Schoene Gruesse */"B?IJj;MEH"
"CX:;",b;for(a/* Best regards my address: */=0;b=c[a++];)
putchar(b-1/(/* Chris cc -ox -xc - && ./x */b/42*2-3)*42);}Hi,
Quoted 4 lines · Emmanuel Deloget
* 0.9.8zh -->
EVP_PKEY_id()is not defined. I'm adding this toopenssl_compat.hand will provide a v2 patch with the change. Once added, OpenVPN compiled successfully and was able to connect to my /2.3 server.
If possible, please do only resend the commit that got changed, not all of it (easier to keep track when Steffan starts sending reviews).
Quoted 5 lines
* 1.0.0t --> compile OK, connect OK
* 1.0.1u --> compile OK, connect OK
* 1.0.2.k --> compile OK, connect OK
Great :-)
Quoted 3 lines
* 1.1.0-git --> compile OK, failure to connect. I'm currently investigating this issue. I'll provide a patch as soon as I fix this (this is a bit ironic ; I may have forgotten something somewhere...).
Interesting. Anything useful in openvpn's logs?
Quoted 2 lines
I don't have much time to test with other OpenSSL versions but I guess you have the infrastructure that will help.
Well, *I* do not have specific "test across various OpenSSL versions" infrastructure, but compiling across our buildbot zoo gives us quite a bit of coverage... and I assume Steffan has more coverage on SSL library versions.
thanks for your work!
gert
Signature · 4 lines
USENET is *not* the non-clickable part of WWW!
//www.muc.de/~gert/
Gert Doering - Munich, Germany [email protected]...
fax: +49-89-35655025 [email protected]...Hi,
Quoted 3 lines · Gert Doering
Interesting. Anything useful in openvpn's logs?
Mon Feb 20 11:57:56 2017 us=371715 OpenSSL: error:0607B083:digital envelope routines:EVP_CipherInit_ex:no cipher set
Mon Feb 20 11:57:56 2017 us=371746 EVP cipher init #2
I found the culprit: OpenSSL's EVP_CipherInit() changed way too much for a 3 lines function. Prior to v1.1, the code did a check on cipher parameter and cleared the EVP context only if cipher was not null. In 1.1, it clears the context unconditionnaly. Having to cope with changes in the interface is not that fun, having to cope with behavior changes is even worse :)
I'm producing an additional commit to work around that change (the proposed change does not depend on the OpenSSL version).
Quoted 11 lines
Quoted 2 lines
I don't have much time to test with other OpenSSL versions but I guess you have the infrastructure that will help.
Well, *I* do not have specific "test across various OpenSSL versions" infrastructure, but compiling across our buildbot zoo gives us quite a bit of coverage... and I assume Steffan has more coverage on SSL library versions.
thanks for your work!
gert
Well, thanks to everyone involved -- all of you have been really kind with me (for now :))
Best regards,
-- Emmanuel Deloget
v2 cover Add support for OpenSSL 1.1.x
In reply to [email protected]...This (limited) series replaces a few patches on the v1 series, namely:
* "OpenSSL: don't use direct access to the internal of EVP_PKEY" This version replaces the previous version and adds function EVP_PKEY_id() which is present in 1.0.0 and later but not in 0.9.8.
* "OpenSSL: use EVP_CipherInit_ex() instead of EVP_CipherInit()"
This version has been compile-tested with the following versions:
* 0.9.8zh
* 1.0.0t
* 1.0.1u
* 1.0.2k
* 1.1.0-git
Each compilation test was followed by a connection test to an OpenVPN server (v2.3). So far, everything seems to work.
Emmanuel Deloget (15):
OpenSSL: don't use direct access to the internal of SSL_CTX
OpenSSL: don't use direct access to the internal of X509_STORE
OpenSSL: don't use direct access to the internal of X509_OBJECT
OpenSSL: don't use direct access to the internal of RSA_METHOD
OpenSSL: don't use direct access to the internal of X509
OpenSSL: don't use direct access to the internal of EVP_PKEY
OpenSSL: don't use direct access to the internal of RSA
OpenSSL: don't use direct access to the internal of DSA
OpenSSL: don't use direct access to the internal of X509_STORE_CTX
OpenSSL: don't use direct access to the internal of EVP_MD_CTX
OpenSSL: don't use direct access to the internal of EVP_CIPHER_CTX
OpenSSL: don't use direct access to the internal of HMAC_CTX
OpenSSL: SSLeay symbols are no longer available in OpenSSL 1.1
OpenSSL: constify getbio() parameters
OpenSSL: use EVP_CipherInit_ex() instead of EVP_CipherInit()
configure.ac | 38 +++ src/openvpn/crypto.c | 8 +- src/openvpn/crypto_backend.h | 42 +++ src/openvpn/crypto_mbedtls.c | 40 +++ src/openvpn/crypto_openssl.c | 54 +++- src/openvpn/httpdigest.c | 78 ++--- src/openvpn/misc.c | 14 +- src/openvpn/ntlm.c | 12 +- src/openvpn/openssl_compat.h | 623 +++++++++++++++++++++++++++++++++++++++ src/openvpn/openvpn.h | 2 +- src/openvpn/push.c | 11 +- src/openvpn/ssl.c | 38 +-- src/openvpn/ssl_openssl.c | 94 +++--- src/openvpn/ssl_verify_openssl.c | 55 ++-- 14 files changed, 963 insertions(+), 146 deletions(-) create mode 100644 src/openvpn/openssl_compat.h
Signature · 1 line
2.7.4
RFC PATCH v2 6/15 OpenSSL: don't use direct access to the internal of EVP_PKEY
OpenSSL 1.1 does not allow us to directly access the internal of any data type, including EVP_PKEY. We have to use the defined functions to do so.
Compatibility with OpenSSL 1.0 is kept by defining the corresponding functions when they are not found in the library.
--- configure.ac | 3 +++ src/openvpn/openssl_compat.h | 42 ++++++++++++++++++++++++++++++++++++++++++ src/openvpn/ssl_openssl.c | 6 +++--- 3 files changed, 48 insertions(+), 3 deletions(-)
configure.ac +3 -0
@@ -906,6 +906,9 @@ if test "${enable_crypto}" = "yes" -a "${with_crypto_library}" = "openssl"; then X509_STORE_get0_objects \ X509_OBJECT_free \ X509_OBJECT_get_type \ + EVP_PKEY_id \ + EVP_PKEY_get0_RSA \ + EVP_PKEY_get0_DSA \ RSA_meth_new \ RSA_meth_free \ RSA_meth_set_pub_enc \
src/openvpn/openssl_compat.h +42 -0
48 lines not on this page · raw message
src/openvpn/ssl_openssl.c +3 -3
@@ -1075,7 +1075,7 @@ tls_ctx_use_external_private_key(struct tls_root_ctx *ctx,/* get the public key */ EVP_PKEY *pkey =X509_get0_pubkey (cert);ASSERT (pkey);/* NULL before SSL_CTX_use_certificate() is called */ - pub_rsa = cert->cert_info->key->pkey->pkey.rsa; + pub_rsa =EVP_PKEY_get0_RSA (pkey);/* initialize RSA object */ rsa->n =BN_dup (pub_rsa->n);
@@ -1680,13 +1680,13 @@ print_details(struct key_state_ssl *ks_ssl, const char *prefix)EVP_PKEY *pkey =X509_get_pubkey (cert);if (pkey !=NULL ) { -if (pkey->type ==EVP_PKEY_RSA && pkey->pkey.rsa !=NULL +if (EVP_PKEY_id (pkey) ==EVP_PKEY_RSA &&EVP_PKEY_get0_RSA (pkey) !=NULL && pkey->pkey.rsa->n !=NULL ) {openvpn_snprintf (s2,sizeof (s2),", %d bit RSA" ,BN_num_bits (pkey->pkey.rsa->n)); } -else if (pkey->type ==EVP_PKEY_DSA && pkey->pkey.dsa !=NULL +else if (EVP_PKEY_id (pkey) ==EVP_PKEY_DSA &&EVP_PKEY_get0_DSA (pkey) !=NULL && pkey->pkey.dsa->p !=NULL ) { openvpn_snprintf(s2, sizeof(s2), ", %d bit DSA",
Signature · 1 line
2.7.4
RFC PATCH v2 15/15 OpenSSL: use EVP_CipherInit_ex() instead of EVP_CipherInit()
In reply to Emmanuel DelogetThe behavior of EVP_CipherInit() changed in OpenSSL 1.1 -- instead of clearing the context when the cipher parameter was !NULL, it now clears the context unconditionnaly. As a result, subsequent calls to the function with additional information now fails.
The bulk work is done by EVP_CipherInit_ex() which has been part of the OpenSSL interface since the dawn of time (0.9.8 already has it). Thus, the change allows us to get the old behavior back instead of relying on dirty tricks.
--- src/openvpn/crypto_openssl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
src/openvpn/crypto_openssl.c +2 -2
@@ -683,7 +683,7 @@ cipher_ctx_init(EVP_CIPHER_CTX *ctx, uint8_t *key, int key_len, crypto_msg(M_FATAL, "EVP set key size"); }#endif -if (!EVP_CipherInit (ctx,NULL , key,NULL , enc)) +if (!EVP_CipherInit_ex (ctx,NULL ,NULL , key,NULL , enc)) {crypto_msg (M_FATAL ,"EVP cipher init #2" ); }
@@ -736,7 +736,7 @@ cipher_ctx_get_cipher_kt(const cipher_ctx_t *ctx)int cipher_ctx_reset (EVP_CIPHER_CTX *ctx,uint8_t *iv_buf) { -return EVP_CipherInit (ctx,NULL ,NULL , iv_buf,-1 ); +return EVP_CipherInit_ex (ctx,NULL ,NULL ,NULL , iv_buf,-1 ); }int
Signature · 1 line
2.7.4
Re: [Openvpn-devel] [RFC PATCH v2 15/15] OpenSSL: use EVP_CipherInit_ex() instead of EVP_CipherInit()
Hi,
Quoted 30 lines · Emmanuel Deloget
The behavior of
EVP_CipherInit()changed in OpenSSL 1.1 -- instead of clearing the context when the cipher parameter was !NULL, it now clears the context unconditionnaly. As a result, subsequent calls to the function with additional information now fails.The bulk work is done by
EVP_CipherInit_ex()which has been part of the OpenSSL interface since the dawn of time (0.9.8 already has it). Thus, the change allows us to get the old behavior back instead of relying on dirty tricks.Signed-off-by Emmanuel Deloget <[email protected]...>--- src/openvpn/crypto_openssl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)src/openvpn/crypto_openssl.c +1
-1@@ -683,7 +683,7 @@ cipher_ctx_init(EVP_CIPHER_CTX *ctx, uint8_t *key, int key_len, crypto_msg(M_FATAL, "EVP set key size"); }#endif -if (!EVP_CipherInit (ctx,NULL , key,NULL , enc)) +if (!EVP_CipherInit_ex (ctx,NULL ,NULL , key,NULL , enc)) {crypto_msg (M_FATAL ,"EVP cipher init #2" ); }
src/openvpn/crypto_openssl.c cipher_ctx_get_cipher_kt(const cipher_ctx_t *ctx) · line 742
Quoted 8 lines
src/openvpn/crypto_openssl.c +1
-1@@ -736,7 +736,7 @@ cipher_ctx_get_cipher_kt(const cipher_ctx_t *ctx)int cipher_ctx_reset (EVP_CIPHER_CTX *ctx,uint8_t *iv_buf) { -return EVP_CipherInit (ctx,NULL ,NULL , iv_buf,-1 ); +return EVP_CipherInit_ex (ctx,NULL ,NULL ,NULL , iv_buf,-1 ); }int
ACK
-Steffan
[Openvpn-devel] [PATCH applied] Re: OpenSSL: use EVP_CipherInit_ex() instead of EVP_CipherInit()
In reply to Emmanuel DelogetYour patch has been applied to the master and release/2.4 branch.
commit 8d00afae88b626c9cf14170a943b33a7ed378070 (master) commit 0fa3df510c10820d00b8f5c77a8730f90189f30d (release/2.4)
Author: Emmanuel Deloget Date: Mon Feb 20 15:32:34 2017 +0100
OpenSSL: use EVP_CipherInit_ex() instead of EVP_CipherInit()
Signed-off-by: Emmanuel Deloget <[email protected]...>
Acked-by: Steffan Karger <[email protected]...>
Message-Id: <2faff7647151d7fe362c1c5db9f97e520444d09b.1487600539.git.logout@...260...>
URL: https://www.mail-archive.com/[email protected]/msg14120.html
Signed-off-by: Gert Doering <[email protected]...>--
kind regards,
Gert Doering