Fix --tls-version-min and --tls-version-max for OpenSSL 1.1+
PATCH 1/3 Fix --tls-version-min and --tls-version-max for OpenSSL 1.1+
As described in <[email protected]...> on the openvpn-devel mailing list, --tls-version-min no longer works with OpenSSL 1.1. Kurt Roeckx posted in a debian bug report:
"This is marked as important because if you switch to openssl 1.1.0 the defaults minimum version in Debian is currently TLS 1.2 and you can't override it with the options that you're currently using (and are deprecated)."
This patch is loosely based on the original patch by Kurt, but solves the issue by adding functions to openssl-compat.h, like we also did for all other openssl 1.1. breakage. This results in not having to add more ifdefs in ssl_openssl.c and thus cleaner code.
--- src/openvpn/openssl_compat.h | 65 ++++++++++++++++++++++++++++++++++++ src/openvpn/options.c | 1 + src/openvpn/ssl_openssl.c | 79 ++++++++++++++++++++++++-------------------- 3 files changed, 109 insertions(+), 36 deletions(-)
src/openvpn/openssl_compat.h +65 -0
@@ -647,4 +647,69 @@ EC_GROUP_order_bits(const EC_GROUP *group)#define RSA_F_RSA_OSSL_PRIVATE_ENCRYPT RSA_F_RSA_EAY_PRIVATE_ENCRYPT#endif +/* TLS Version defines are new in OpenSSL 1.1 */ +#ifndef TLS1_0_VERSION +#define TLS1_0_VERSION 0x0301 +#endif +#ifndef TLS1_1_VERSION +#define TLS1_1_VERSION 0x0302 +#endif +#ifndef TLS1_2_VERSION +#define TLS1_2_VERSION 0x0303 +#endif + +#ifndef SSL_CTX_set_min_proto_version +/** Mimics SSL_CTX_set_min_proto_version for OpenSSL < 1.1 */ +static inline void +SSL_CTX_set_min_proto_version (SSL_CTX *ctx,long tls_ver_min) +{ +long sslopt = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;/* Never do < TLS 1.0 */ + +if (tls_ver_min >TLS1_0_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1; + } +#ifdef SSL_OP_NO_TLSv1_1 +if (tls_ver_min >TLS1_1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_1; + } +#endif +#ifdef SSL_OP_NO_TLSv1_2 +if (tls_ver_min >TLS1_2_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_2; + } +#endif +SSL_CTX_set_options (ctx, sslopt); +} +#endif /* SSL_CTX_set_min_proto_version */ + +#ifndef SSL_CTX_set_max_proto_version +/** Mimics SSL_CTX_set_max_proto_version for OpenSSL < 1.1 */ +static inline void +SSL_CTX_set_max_proto_version (SSL_CTX *ctx,long tls_ver_max) +{ +long sslopt =0 ; + +if (tls_ver_max <TLS1_0_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1; + } +#ifdef SSL_OP_NO_TLSv1_1 +if (tls_ver_max <TLS1_1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_1; + } +#endif +#ifdef SSL_OP_NO_TLSv1_2 +if (tls_ver_max <TLS1_2_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_2; + } +#endif +SSL_CTX_set_options (ctx, sslopt); +} +#endif /* SSL_CTX_set_max_proto_version */ +#endif /* OPENSSL_COMPAT_H_ */
src/openvpn/options.c +1 -0
@@ -870,6 +870,7 @@ init_options(struct options *o, const bool init_gc)#ifdef ENABLE_PREDICTION_RESISTANCE o->use_prediction_resistance = false;#endif + o->ssl_flags = (TLS_VER_1_0 <<SSLF_TLS_VERSION_MIN_SHIFT ); o->key_method =2 ; o->tls_timeout =2 ; o->renegotiate_bytes =-1 ;
src/openvpn/ssl_openssl.c +43 -36
100 lines not on this page · raw message
Signature · 1 line
2.14.1
PATCH 2/3 Add support for TLS 1.3 in --tls-version-{min, max}
Tested with the current openssl master branch for TLS 1.3 support.
mbed TLS has no public builds with TLS 1.3 support yet, so nothing to do there right now.
--- src/openvpn/ssl.c | 4 ++++ src/openvpn/ssl_backend.h | 1 + src/openvpn/ssl_openssl.c | 10 +++++++++- 3 files changed, 14 insertions(+), 1 deletion(-)
src/openvpn/ssl.c +4 -0
@@ -530,6 +530,10 @@ tls_version_parse(const char *vstr, const char *extra) {return TLS_VER_1_2 ; } + else if (!strcmp(vstr, "1.3") && TLS_VER_1_3 <= max_version) + { +return TLS_VER_1_3 ; + } else if (extra && !strcmp(extra, "or-highest")) {return max_version;
src/openvpn/ssl_backend.h +1 -0
@@ -114,6 +114,7 @@ void tls_clear_error(void);#define TLS_VER_1_0 1#define TLS_VER_1_1 2#define TLS_VER_1_2 3 +#define TLS_VER_1_3 4int tls_version_parse (const char *vstr,const char *extra);/**
src/openvpn/ssl_openssl.c +9 -1
@@ -206,7 +206,9 @@ info_callback(INFO_CALLBACK_SSL_CONST SSL *s, int where, int ret)int tls_version_max (void ) { -#if defined(TLS1_2_VERSION ) || defined(SSL_OP_NO_TLSv1_2) +#if defined(TLS1_3_VERSION ) +return TLS_VER_1_3 ; +#elif defined(TLS1_2_VERSION ) || defined(SSL_OP_NO_TLSv1_2)return TLS_VER_1_2 ;#elif defined(TLS1_1_VERSION ) || defined(SSL_OP_NO_TLSv1_1)return TLS_VER_1_1 ;
@@ -231,6 +233,12 @@ openssl_tls_version(int ver) {return TLS1_2_VERSION ; } +#if defined(TLS1_3_VERSION ) + else if (ver == TLS_VER_1_3) + { +return TLS1_3_VERSION ; + } +#endif return 0 ; }
Signature · 1 line
2.14.1
[Openvpn-devel] [PATCH applied] Re: Add support for TLS 1.3 in --tls-version-{min, max}
Straightforward extention of the current code to add another branch for 1.3. Since it's really trivial, does not change existing code paths, and we want 2.4 to be "ready for TLS 1.3 when it shows up", applied to 2.4 as well.
Your patch has been applied to the master and release/2.4 branch.
commit 8ca9eda119638a88863118affd69dfaf8b867c92 (master) commit 59dbb8602f30d278bd152a4a736c2af8345368eb (release/2.4)
Author: Steffan Karger Date: Sun Nov 26 15:15:54 2017 +0100
Add support for TLS 1.3 in --tls-version-{min, max}
Signed-off-by: Steffan Karger <[email protected]...>
Acked-by: Gert Doering <[email protected]...>
Message-Id: <[email protected]...>
URL: https://www.mail-archive.com/[email protected]/msg15932.html
Signed-off-by: Gert Doering <[email protected]...>--
kind regards,
Gert Doering
PATCH 3/3 tls_ctx_set_tls_versions: move verify_flags to where it is used
In reply to Steffan KargerMinor cleanup of this function now that we are allowed to write C99: move (and rename) flags to the code where it's actually used to improve readability.
(I originally did this as part of the tls-version-{min,max} patch for openssl 1.1, but that made the diff hard to read.)
--- src/openvpn/ssl_openssl.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
src/openvpn/ssl_openssl.c +4 -6
@@ -262,9 +262,6 @@ tls_ctx_set_options(struct tls_root_ctx *ctx, unsigned int ssl_flags) {ASSERT (NULL != ctx); -/* default certificate verification flags */ -int flags =SSL_VERIFY_PEER |SSL_VERIFY_FAIL_IF_NO_PEER_CERT ; -/* process SSL options */ long sslopt =SSL_OP_SINGLE_DH_USE |SSL_OP_NO_TICKET ;#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
@@ -282,17 +279,18 @@ tls_ctx_set_options(struct tls_root_ctx *ctx, unsigned int ssl_flags)SSL_CTX_set_default_passwd_cb (ctx->ctx, pem_password_callback);/* Require peer certificate verification */ +int verify_flags =SSL_VERIFY_PEER |SSL_VERIFY_FAIL_IF_NO_PEER_CERT ;#if P2MP_SERVER if (ssl_flags &SSLF_CLIENT_CERT_NOT_REQUIRED ) { - flags =0 ; + verify_flags =0 ; }else if (ssl_flags &SSLF_CLIENT_CERT_OPTIONAL ) { - flags =SSL_VERIFY_PEER ; + verify_flags =SSL_VERIFY_PEER ; }#endif -SSL_CTX_set_verify (ctx->ctx, flags, verify_callback); +SSL_CTX_set_verify (ctx->ctx, verify_flags, verify_callback);SSL_CTX_set_info_callback (ctx->ctx, info_callback); }
Signature · 1 line
2.14.1
[Openvpn-devel] [PATCH applied] Re: tls_ctx_set_tls_versions: move verify_flags to where it is used
Cleanup, no effective code change.
Your patch has been applied to the master branch.
commit e05aca4517b666740b384399348b995a3a646629
Author: Steffan Karger Date: Sun Nov 26 15:15:55 2017 +0100
tls_ctx_set_tls_versions: move verify_flags to where it is used
Signed-off-by: Steffan Karger <[email protected]...>
Acked-by: Gert Doering <[email protected]...>
Message-Id: <[email protected]...>
URL: https://www.mail-archive.com/[email protected]/msg15931.html
Signed-off-by: Gert Doering <[email protected]...>--
kind regards,
Gert Doering
In gmane.network.openvpn.devel, Steffan Karger wrote:
Hi Steffan,
Quoted 9 lines
As described in <[email protected]...> on the openvpn-devel mailing list, --tls-version-min no longer works with OpenSSL 1.1. Kurt Roeckx posted in a debian bug report:
"This is marked as important because if you switch to openssl 1.1.0 the defaults minimum version in Debian is currently TLS 1.2 and you can't override it with the options that you're currently using (and are deprecated)."
Quoted 4 lines
This patch is loosely based on the original patch by Kurt, but solves the issue by adding functions to
openssl-compat.h, like we also did for all other openssl 1.1. breakage. This results in not having to add more ifdefs inssl_openssl.cand thus cleaner code.
I have forwarded your patch to Kurt and asked for feedback. See attached mail.
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=873302#32
Bernhard
Quoted 6 lines · Bernhard Schmidt
Hi Kurt,
Steffan has posted a patch for this that is losely based on yours. It is not merged yet, comments welcome.
I have some comments:
- It has:
+/* TLS Version defines are new in OpenSSL 1.1 */
+#ifndef TLS1_0_VERSION
+#define TLS1_0_VERSION 0x0301
+#endif
+#ifndef TLS1_1_VERSION
+#define TLS1_1_VERSION 0x0302
+#endif
+#ifndef TLS1_2_VERSION
+#define TLS1_2_VERSION 0x0303
+#endif
It's TLS1_VERSION (not TLS1_0_VERSION)
The defines all exist in at least 1.0.1, the version that added support for TLS 1.1 and 1.2
- It calls SSL_CTX_set_min_proto_version() unconditionally, overriding the library default. In the 1.0.2 case SSLv2 and SSLv3 are then disabled, in the 1.1 case it could enable SSLv3.
- openssl_tls_version() should probably add SSL3_VERSION support.
Kurt
Hi Bernard, Kurt,
Quoted 14 lines · Bernhard Schmidt
Quoted 9 lines
As described in <[email protected]...> on the openvpn-devel mailing list, --tls-version-min no longer works with OpenSSL 1.1. Kurt Roeckx posted in a debian bug report:
"This is marked as important because if you switch to openssl 1.1.0 the defaults minimum version in Debian is currently TLS 1.2 and you can't override it with the options that you're currently using (and are deprecated)."
Quoted 4 lines
This patch is loosely based on the original patch by Kurt, but solves the issue by adding functions to
openssl-compat.h, like we also did for all other openssl 1.1. breakage. This results in not having to add more ifdefs inssl_openssl.cand thus cleaner code.
Quoted 4 lines
I have forwarded your patch to Kurt and asked for feedback. See attached mail.
Thanks!
Quoted 1 line · Kurt Roeckx
I have some comments:
Also thanks!
Quoted 12 lines
- It has:
src/openvpn/openssl_compat.h +10
-0+/* TLS Version defines are new in OpenSSL 1.1 */ +#ifndef TLS1_0_VERSION +#define TLS1_0_VERSION 0x0301 +#endif +#ifndef TLS1_1_VERSION +#define TLS1_1_VERSION 0x0302 +#endif +#ifndef TLS1_2_VERSION +#define TLS1_2_VERSION 0x0303 +#endif
Quoted 1 line
It's
TLS1_VERSION(notTLS1_0_VERSION)
Oops, will fix.
Quoted 2 lines
The defines all exist in at least 1.0.1, the version that added support for TLS 1.1 and 1.2
Good, then we won't need this in master. (But we do in release/2.4 because there we still support 0.9.8 as suse still maintains it.)
Quoted 3 lines
- It calls
SSL_CTX_set_min_proto_version()unconditionally, overriding the library default. In the 1.0.2 case SSLv2 and SSLv3 are then disabled, in the 1.1 case it could enable SSLv3.
This is something I pondered about, and once again now you mention it. OpenVPN < 2.3.4 (and OpenSSL < 1.0.1), which are still widely used by our user base, do not support TLS 1.1+. Combined with the fact that many HTTPS-style TLS attacks do not work for OpenVPN (the record layer data is not attacker controlled like in browser), I opted to just fix the minimum at 1.0 and keep the code slightly simpler.
But I think it's okay to confront users with old cruft, and follow the system defaults. Since users can re-enable TLS 1.0 if they really want, I think that should be okay. The v2 of this patch will obey the system defaults.
Quoted 1 line
-
openssl_tls_version()should probably addSSL3_VERSIONsupport.
Nope - OpenVPN never supported SSLv3 and never will.
-Steffan
PATCH v2 1/3 Fix --tls-version-min and --tls-version-max for OpenSSL 1.1+
In reply to Bernhard SchmidtAs described in <[email protected]...> on the openvpn-devel mailing list, --tls-version-min no longer works with OpenSSL 1.1. Kurt Roeckx posted in a debian bug report:
"This is marked as important because if you switch to openssl 1.1.0 the defaults minimum version in Debian is currently TLS 1.2 and you can't override it with the options that you're currently using (and are deprecated)."
This patch is loosely based on the original patch by Kurt, but solves the issue by adding functions to openssl-compat.h, like we also did for all other openssl 1.1. breakage. This results in not having to add more ifdefs in ssl_openssl.c and thus cleaner code.
---
v2: fix define name, obey system lib default minimum version
Note: this patch does not cherry-pick to release/2.4 nicely. Once the one for master has been accepted, I'll send a backport for release/2.4.
src/openvpn/openssl_compat.h | 63 ++++++++++++++++++++++++++++++++ src/openvpn/ssl_openssl.c | 86 +++++++++++++++++++++++++------------------- 2 files changed, 113 insertions(+), 36 deletions(-)
src/openvpn/openssl_compat.h +63 -0
@@ -647,4 +647,67 @@ EC_GROUP_order_bits(const EC_GROUP *group)#define RSA_F_RSA_OSSL_PRIVATE_ENCRYPT RSA_F_RSA_EAY_PRIVATE_ENCRYPT#endif +#ifndef SSL_CTX_get_min_proto_version +/** Dummy SSL_CTX_get_min_proto_version for OpenSSL < 1.1 (not really needed) */ +static inline int +SSL_CTX_get_min_proto_version (SSL_CTX *ctx) +{ +return 0 ; +} +#endif /* SSL_CTX_get_min_proto_version */ + +#ifndef SSL_CTX_set_min_proto_version +/** Mimics SSL_CTX_set_min_proto_version for OpenSSL < 1.1 */ +static inline void +SSL_CTX_set_min_proto_version (SSL_CTX *ctx,long tls_ver_min) +{ +long sslopt = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;/* Never do < TLS 1.0 */ + +if (tls_ver_min >TLS1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1; + } +#ifdef SSL_OP_NO_TLSv1_1 +if (tls_ver_min >TLS1_1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_1; + } +#endif +#ifdef SSL_OP_NO_TLSv1_2 +if (tls_ver_min >TLS1_2_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_2; + } +#endif +SSL_CTX_set_options (ctx, sslopt); +} +#endif /* SSL_CTX_set_min_proto_version */ + +#ifndef SSL_CTX_set_max_proto_version +/** Mimics SSL_CTX_set_max_proto_version for OpenSSL < 1.1 */ +static inline void +SSL_CTX_set_max_proto_version (SSL_CTX *ctx,long tls_ver_max) +{ +long sslopt =0 ; + +if (tls_ver_max <TLS1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1; + } +#ifdef SSL_OP_NO_TLSv1_1 +if (tls_ver_max <TLS1_1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_1; + } +#endif +#ifdef SSL_OP_NO_TLSv1_2 +if (tls_ver_max <TLS1_2_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_2; + } +#endif +SSL_CTX_set_options (ctx, sslopt); +} +#endif /* SSL_CTX_set_max_proto_version */ +#endif /* OPENSSL_COMPAT_H_ */
src/openvpn/ssl_openssl.c +50 -36
107 lines not on this page · raw message
Signature · 1 line
2.14.1
Hi,
The patch is good except for some issues that are easy to fix:
Quoted 3 lines · Steffan Karger
As described in <[email protected]...> on the openvpn-devel mailing list, --tls-version-min no longer works with OpenSSL 1.1. Kurt Roeckx posted in a debian bug report:
I did not see this behaviour in locally built openssl 1.1, and so did some digging..
Our current approach still works on stock-built openssl 1.1 (though deprecated). But some distros (e.g., Debian unstable) are patching openssl-1.1 to set TLS 1.2 as the default min version. That can be over-ridden only using the new min/max_proto_version API calls. Debian has recently backed-off on this, but distros restricting TLS versions is something we need to cope with.
Even otherwise directly setting the min/max values is better. And the old and new methods do not work well together. So this change is good to have, independent of the target OS/distro.
Anyway, I want to use this in the cryptoapi patch: why else would anyone do the thankless reviewing job :)
Quoted 135 lines
"This is marked as important because if you switch to openssl 1.1.0 the defaults minimum version in Debian is currently TLS 1.2 and you can't override it with the options that you're currently using (and are deprecated)."
This patch is loosely based on the original patch by Kurt, but solves the issue by adding functions to
openssl-compat.h, like we also did for all other openssl 1.1. breakage. This results in not having to add more ifdefs inssl_openssl.cand thus cleaner code.Signed-off-by Steffan Karger <[email protected]...>---
v2: fix define name, obey system lib default minimum versionNote: this patch does not cherry-pick to release/2.4 nicely. Once the one for master has been accepted, I'll send a backport for release/2.4.
src/openvpn/openssl_compat.h | 63 ++++++++++++++++++++++++++++++++ src/openvpn/ssl_openssl.c | 86 +++++++++++++++++++++++++------------------- 2 files changed, 113 insertions(+), 36 deletions(-)src/openvpn/openssl_compat.h +63
-0@@ -647,4 +647,67 @@ EC_GROUP_order_bits(const EC_GROUP *group)#define RSA_F_RSA_OSSL_PRIVATE_ENCRYPT RSA_F_RSA_EAY_PRIVATE_ENCRYPT#endif +#ifndef SSL_CTX_get_min_proto_version +/** Dummy SSL_CTX_get_min_proto_version for OpenSSL < 1.1 (not really needed) */ +static inline int +SSL_CTX_get_min_proto_version (SSL_CTX *ctx) +{ +return 0 ; +} +#endif /* SSL_CTX_get_min_proto_version */ + +#ifndef SSL_CTX_set_min_proto_version +/** Mimics SSL_CTX_set_min_proto_version for OpenSSL < 1.1 */ +static inline void +SSL_CTX_set_min_proto_version (SSL_CTX *ctx,long tls_ver_min) +{ +long sslopt = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;/* Never do < TLS 1.0 */ + +if (tls_ver_min >TLS1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1; + } +#ifdef SSL_OP_NO_TLSv1_1 +if (tls_ver_min >TLS1_1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_1; + } +#endif +#ifdef SSL_OP_NO_TLSv1_2 +if (tls_ver_min >TLS1_2_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_2; + } +#endif +SSL_CTX_set_options (ctx, sslopt); +} +#endif /* SSL_CTX_set_min_proto_version */ + +#ifndef SSL_CTX_set_max_proto_version +/** Mimics SSL_CTX_set_max_proto_version for OpenSSL < 1.1 */ +static inline void +SSL_CTX_set_max_proto_version (SSL_CTX *ctx,long tls_ver_max) +{ +long sslopt =0 ; + +if (tls_ver_max <TLS1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1; + } +#ifdef SSL_OP_NO_TLSv1_1 +if (tls_ver_max <TLS1_1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_1; + } +#endif +#ifdef SSL_OP_NO_TLSv1_2 +if (tls_ver_max <TLS1_2_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_2; + } +#endif +SSL_CTX_set_options (ctx, sslopt); +} +#endif /* SSL_CTX_set_max_proto_version */ +#endif /* OPENSSL_COMPAT_H_ */ src/openvpn/ssl_openssl.c +24
-2@@ -206,15 +206,56 @@ info_callback(INFO_CALLBACK_SSL_CONST SSL *s, int where, int ret)int tls_version_max (void ) { -#if defined(SSL_OP_NO_TLSv1_2) +#if defined(TLS1_2_VERSION ) || defined(SSL_OP_NO_TLSv1_2)return TLS_VER_1_2 ; -#elif defined(SSL_OP_NO_TLSv1_1) +#elif defined(TLS1_1_VERSION ) || defined(SSL_OP_NO_TLSv1_1)return TLS_VER_1_1 ;#else return TLS_VER_1_0 ;#endif } +/** Convert internal version number to openssl version number */ +static int +openssl_tls_version (int ver) +{ +if (ver ==TLS_VER_1_0 ) + { +return TLS1_VERSION ; + } +else if (ver ==TLS_VER_1_1 ) + { +return TLS1_1_VERSION ; + } +else if (ver ==TLS_VER_1_2 ) + { +return TLS1_2_VERSION ; + } +return 0 ; +} + +static void +tls_ctx_set_tls_versions (struct tls_root_ctx *ctx,unsigned int ssl_flags) +{
src/openvpn/ssl_openssl.c info_callback(INFO_CALLBACK_SSL_CONST SSL *s, int where, int ret) · line 249
Quoted 10 lines
src/openvpn/ssl_openssl.c +10
-0+int tls_ver_min =openssl_tls_version ( + (ssl_flags >>SSLF_TLS_VERSION_MIN_SHIFT ) &SSLF_TLS_VERSION_MIN_MASK ); +int tls_ver_max =openssl_tls_version ( + (ssl_flags >>SSLF_TLS_VERSION_MAX_SHIFT ) &SSLF_TLS_VERSION_MAX_MASK ); + +if (!tls_ver_min) + { +/* Enforce at least TLS 1.0 */ +int cur_min =SSL_CTX_get_min_proto_version (ctx->ctx); + tls_ver_min = cur_min <TLS1_VERSION ?TLS_VER_1_0 : cur_min;
That should be
tls_ver_min = cur_min < TLS1_VERSION ? TLS1_VERSION : cur_min;
src/openvpn/ssl_openssl.c info_callback(INFO_CALLBACK_SSL_CONST SSL *s, int where, int ret) · line 251
Quoted 2 lines
src/openvpn/ssl_openssl.c +2
-0+ } +SSL_CTX_set_min_proto_version (ctx->ctx, tls_ver_min);
This call can potentially fail in openssl 1.1, though unlikely. As a sane minimum is
important, we should check the return value and do something sensible with it. Actually it does fail with the above bug and it could fail in some other convoluted
situations.
src/openvpn/ssl_openssl.c info_callback(INFO_CALLBACK_SSL_CONST SSL *s, int where, int ret) · line 255
Quoted 4 lines
src/openvpn/ssl_openssl.c +4
-0+ +if (tls_ver_max) + { +SSL_CTX_set_max_proto_version (ctx->ctx, tls_ver_max);
This also can potentially fail. Not critical unlike the minimum value, but still a check of the return value and a helpful error message is useful.
Quoted 47 lines
src/openvpn/ssl_openssl.c +6
-32+ } +} +void tls_ctx_set_options (struct tls_root_ctx *ctx,unsigned int ssl_flags) {@@ -223,42 +264,15 @@ tls_ctx_set_options(struct tls_root_ctx *ctx, unsigned int ssl_flags)/* default certificate verification flags */ int flags =SSL_VERIFY_PEER |SSL_VERIFY_FAIL_IF_NO_PEER_CERT ; -/* process SSL options including minimum TLS version we will accept from peer */ - { -long sslopt =SSL_OP_SINGLE_DH_USE |SSL_OP_NO_TICKET | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; -int tls_ver_max =TLS_VER_UNSPEC ; -const int tls_ver_min = - (ssl_flags >>SSLF_TLS_VERSION_MIN_SHIFT ) &SSLF_TLS_VERSION_MIN_MASK ; - - tls_ver_max = - (ssl_flags >>SSLF_TLS_VERSION_MAX_SHIFT ) &SSLF_TLS_VERSION_MAX_MASK ; -if (tls_ver_max <=TLS_VER_UNSPEC ) - { - tls_ver_max =tls_version_max (); - } - -if (tls_ver_min >TLS_VER_1_0 || tls_ver_max <TLS_VER_1_0 ) - { - sslopt |= SSL_OP_NO_TLSv1; - } -#ifdef SSL_OP_NO_TLSv1_1 -if (tls_ver_min >TLS_VER_1_1 || tls_ver_max <TLS_VER_1_1 ) - { - sslopt |= SSL_OP_NO_TLSv1_1; - } -#endif -#ifdef SSL_OP_NO_TLSv1_2 -if (tls_ver_min >TLS_VER_1_2 || tls_ver_max <TLS_VER_1_2 ) - { - sslopt |= SSL_OP_NO_TLSv1_2; - } -#endif +/* process SSL options */ +long sslopt =SSL_OP_SINGLE_DH_USE |SSL_OP_NO_TICKET ;#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE - sslopt |=SSL_OP_CIPHER_SERVER_PREFERENCE ; + sslopt |=SSL_OP_CIPHER_SERVER_PREFERENCE ;#endif - sslopt |=SSL_OP_NO_COMPRESSION ;
src/openvpn/ssl_openssl.c tls_ctx_set_options(struct tls_root_ctx *ctx, unsigned int ssl_flags)
Quoted 10 lines
src/openvpn/ssl_openssl.c +4
-3-SSL_CTX_set_options (ctx->ctx, sslopt); - } + sslopt |=SSL_OP_NO_COMPRESSION ; +SSL_CTX_set_options (ctx->ctx, sslopt); + +tls_ctx_set_tls_versions (ctx, ssl_flags);#ifdef SSL_MODE_RELEASE_BUFFERS SSL_CTX_set_mode (ctx->ctx,SSL_MODE_RELEASE_BUFFERS ); --
Debian has recently (Nov 2017) back-tracked on setting 1.2 as the default min version, so testing against the original bug report is now hard.
But this passes my tests with custom built openssl and a recently updated debian unstable installation (after the bug fix mentioned above).
Finally, there is a minor issue with openssl 1.1's macros for SSL_CTX_get_min/max_proto_version (long argument passed a NULL) but I think we can live with the compiler warning until they fix it upstream.
Regards,
Selva
Hi,
Quoted 7 lines · Selva Nair
The patch is good except for some issues that are easy to fix:
Quoted 3 lines · Steffan Karger
As described in <[email protected]...> on the openvpn-devel mailing list, --tls-version-min no longer works with OpenSSL 1.1. Kurt Roeckx posted in a debian bug report:
Quoted 8 lines
I did not see this behaviour in locally built openssl 1.1, and so did some digging..
Our current approach still works on stock-built openssl 1.1 (though deprecated). But some distros (e.g., Debian unstable) are patching openssl-1.1 to set TLS 1.2 as the default min version. That can be over-ridden only using the new min/max_proto_version API calls. Debian has recently backed-off on this, but distros restricting TLS versions is something we need to cope with.
Ah, that explains why tincantech couldn't reproduce the original issue while testing!
Quoted 6 lines
Even otherwise directly setting the min/max values is better. And the old and new methods do not work well together. So this change is good to have, independent of the target OS/distro.
Anyway, I want to use this in the cryptoapi patch: why else would anyone do the thankless reviewing job :)
So let me thank you right here for reviewing!
Quoted 147 lines
Quoted 134 lines
"This is marked as important because if you switch to openssl 1.1.0 the defaults minimum version in Debian is currently TLS 1.2 and you can't override it with the options that you're currently using (and are deprecated)."
This patch is loosely based on the original patch by Kurt, but solves the issue by adding functions to
openssl-compat.h, like we also did for all other openssl 1.1. breakage. This results in not having to add more ifdefs inssl_openssl.cand thus cleaner code.Signed-off-by Steffan Karger <[email protected]...>---
v2: fix define name, obey system lib default minimum versionNote: this patch does not cherry-pick to release/2.4 nicely. Once the one for master has been accepted, I'll send a backport for release/2.4.
src/openvpn/openssl_compat.h | 63 ++++++++++++++++++++++++++++++++ src/openvpn/ssl_openssl.c | 86 +++++++++++++++++++++++++------------------- 2 files changed, 113 insertions(+), 36 deletions(-)src/openvpn/openssl_compat.h +63
-0@@ -647,4 +647,67 @@ EC_GROUP_order_bits(const EC_GROUP *group)#define RSA_F_RSA_OSSL_PRIVATE_ENCRYPT RSA_F_RSA_EAY_PRIVATE_ENCRYPT#endif +#ifndef SSL_CTX_get_min_proto_version +/** Dummy SSL_CTX_get_min_proto_version for OpenSSL < 1.1 (not really needed) */ +static inline int +SSL_CTX_get_min_proto_version (SSL_CTX *ctx) +{ +return 0 ; +} +#endif /* SSL_CTX_get_min_proto_version */ + +#ifndef SSL_CTX_set_min_proto_version +/** Mimics SSL_CTX_set_min_proto_version for OpenSSL < 1.1 */ +static inline void +SSL_CTX_set_min_proto_version (SSL_CTX *ctx,long tls_ver_min) +{ +long sslopt = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;/* Never do < TLS 1.0 */ + +if (tls_ver_min >TLS1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1; + } +#ifdef SSL_OP_NO_TLSv1_1 +if (tls_ver_min >TLS1_1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_1; + } +#endif +#ifdef SSL_OP_NO_TLSv1_2 +if (tls_ver_min >TLS1_2_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_2; + } +#endif +SSL_CTX_set_options (ctx, sslopt); +} +#endif /* SSL_CTX_set_min_proto_version */ + +#ifndef SSL_CTX_set_max_proto_version +/** Mimics SSL_CTX_set_max_proto_version for OpenSSL < 1.1 */ +static inline void +SSL_CTX_set_max_proto_version (SSL_CTX *ctx,long tls_ver_max) +{ +long sslopt =0 ; + +if (tls_ver_max <TLS1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1; + } +#ifdef SSL_OP_NO_TLSv1_1 +if (tls_ver_max <TLS1_1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_1; + } +#endif +#ifdef SSL_OP_NO_TLSv1_2 +if (tls_ver_max <TLS1_2_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_2; + } +#endif +SSL_CTX_set_options (ctx, sslopt); +} +#endif /* SSL_CTX_set_max_proto_version */ +#endif /* OPENSSL_COMPAT_H_ */ src/openvpn/ssl_openssl.c +24
-2@@ -206,15 +206,56 @@ info_callback(INFO_CALLBACK_SSL_CONST SSL *s, int where, int ret)int tls_version_max (void ) { -#if defined(SSL_OP_NO_TLSv1_2) +#if defined(TLS1_2_VERSION ) || defined(SSL_OP_NO_TLSv1_2)return TLS_VER_1_2 ; -#elif defined(SSL_OP_NO_TLSv1_1) +#elif defined(TLS1_1_VERSION ) || defined(SSL_OP_NO_TLSv1_1)return TLS_VER_1_1 ;#else return TLS_VER_1_0 ;#endif } +/** Convert internal version number to openssl version number */ +static int +openssl_tls_version (int ver) +{ +if (ver ==TLS_VER_1_0 ) + { +return TLS1_VERSION ; + } +else if (ver ==TLS_VER_1_1 ) + { +return TLS1_1_VERSION ; + } +else if (ver ==TLS_VER_1_2 ) + { +return TLS1_2_VERSION ; + } +return 0 ; +} + +static void +tls_ctx_set_tls_versions (struct tls_root_ctx *ctx,unsigned int ssl_flags) +{src/openvpn/ssl_openssl.c info_callback(INFO_CALLBACK_SSL_CONST SSL *s, int where, int ret) · line 249
Quoted 10 lines
src/openvpn/ssl_openssl.c +10
-0+int tls_ver_min =openssl_tls_version ( + (ssl_flags >>SSLF_TLS_VERSION_MIN_SHIFT ) &SSLF_TLS_VERSION_MIN_MASK ); +int tls_ver_max =openssl_tls_version ( + (ssl_flags >>SSLF_TLS_VERSION_MAX_SHIFT ) &SSLF_TLS_VERSION_MAX_MASK ); + +if (!tls_ver_min) + { +/* Enforce at least TLS 1.0 */ +int cur_min =SSL_CTX_get_min_proto_version (ctx->ctx); + tls_ver_min = cur_min <TLS1_VERSION ?TLS_VER_1_0 : cur_min;That should be
Quoted 1 line
tls_ver_min=cur_min<TLS1_VERSION?TLS1_VERSION:cur_min;
Oh, darn, indeed.
Quoted 9 lines
src/openvpn/ssl_openssl.c info_callback(INFO_CALLBACK_SSL_CONST SSL *s, int where, int ret) · line 251
Quoted 2 lines
src/openvpn/ssl_openssl.c +2
-0+ } +SSL_CTX_set_min_proto_version (ctx->ctx, tls_ver_min);This call can potentially fail in openssl 1.1, though unlikely. As a sane minimum is
important, we should check the return value and do something sensible with it. Actually it does fail with the above bug and it could fail in some other convoluted
situations.
Will fix.
Quoted 7 lines
src/openvpn/ssl_openssl.c info_callback(INFO_CALLBACK_SSL_CONST SSL *s, int where, int ret) · line 255
Quoted 4 lines
src/openvpn/ssl_openssl.c +4
-0+ +if (tls_ver_max) + { +SSL_CTX_set_max_proto_version (ctx->ctx, tls_ver_max);This also can potentially fail. Not critical unlike the minimum value, but still a check of the return value and a helpful error message is useful.
Will fix too.
Quoted 61 lines
Quoted 47 lines
src/openvpn/ssl_openssl.c +6
-32+ } +} +void tls_ctx_set_options (struct tls_root_ctx *ctx,unsigned int ssl_flags) {@@ -223,42 +264,15 @@ tls_ctx_set_options(struct tls_root_ctx *ctx, unsigned int ssl_flags)/* default certificate verification flags */ int flags =SSL_VERIFY_PEER |SSL_VERIFY_FAIL_IF_NO_PEER_CERT ; -/* process SSL options including minimum TLS version we will accept from peer */ - { -long sslopt =SSL_OP_SINGLE_DH_USE |SSL_OP_NO_TICKET | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; -int tls_ver_max =TLS_VER_UNSPEC ; -const int tls_ver_min = - (ssl_flags >>SSLF_TLS_VERSION_MIN_SHIFT ) &SSLF_TLS_VERSION_MIN_MASK ; - - tls_ver_max = - (ssl_flags >>SSLF_TLS_VERSION_MAX_SHIFT ) &SSLF_TLS_VERSION_MAX_MASK ; -if (tls_ver_max <=TLS_VER_UNSPEC ) - { - tls_ver_max =tls_version_max (); - } - -if (tls_ver_min >TLS_VER_1_0 || tls_ver_max <TLS_VER_1_0 ) - { - sslopt |= SSL_OP_NO_TLSv1; - } -#ifdef SSL_OP_NO_TLSv1_1 -if (tls_ver_min >TLS_VER_1_1 || tls_ver_max <TLS_VER_1_1 ) - { - sslopt |= SSL_OP_NO_TLSv1_1; - } -#endif -#ifdef SSL_OP_NO_TLSv1_2 -if (tls_ver_min >TLS_VER_1_2 || tls_ver_max <TLS_VER_1_2 ) - { - sslopt |= SSL_OP_NO_TLSv1_2; - } -#endif +/* process SSL options */ +long sslopt =SSL_OP_SINGLE_DH_USE |SSL_OP_NO_TICKET ;#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE - sslopt |=SSL_OP_CIPHER_SERVER_PREFERENCE ; + sslopt |=SSL_OP_CIPHER_SERVER_PREFERENCE ;#endif - sslopt |=SSL_OP_NO_COMPRESSION ;src/openvpn/ssl_openssl.c tls_ctx_set_options(struct tls_root_ctx *ctx, unsigned int ssl_flags)
Quoted 10 lines
src/openvpn/ssl_openssl.c +4
-3-SSL_CTX_set_options (ctx->ctx, sslopt); - } + sslopt |=SSL_OP_NO_COMPRESSION ; +SSL_CTX_set_options (ctx->ctx, sslopt); + +tls_ctx_set_tls_versions (ctx, ssl_flags);#ifdef SSL_MODE_RELEASE_BUFFERS SSL_CTX_set_mode (ctx->ctx,SSL_MODE_RELEASE_BUFFERS ); --Debian has recently (Nov 2017) back-tracked on setting 1.2 as the default min version, so testing against the original bug report is now hard.
Quoted 6 lines
But this passes my tests with custom built openssl and a recently updated debian unstable installation (after the bug fix mentioned above).
Finally, there is a minor issue with openssl 1.1's macros for SSL_CTX_get_min/max_proto_version (long argument passed a NULL) but I think we can live with the compiler warning until they fix it upstream.
tincantech reported this too, so I created a pull request:
https://github.com/openssl/openssl/pull/5099
v3 coming soon.
Thanks,
-Steffan
PATCH v3 1/3 Fix --tls-version-min and --tls-version-max for OpenSSL 1.1+
In reply to Selva NairAs described in <[email protected]...> on the openvpn-devel mailing list, --tls-version-min no longer works with OpenSSL 1.1. Kurt Roeckx posted in a debian bug report:
"This is marked as important because if you switch to openssl 1.1.0 the defaults minimum version in Debian is currently TLS 1.2 and you can't override it with the options that you're currently using (and are deprecated)."
This patch is loosely based on the original patch by Kurt, but solves the issue by adding functions to openssl-compat.h, like we also did for all other openssl 1.1. breakage. This results in not having to add more ifdefs in ssl_openssl.c and thus cleaner code.
---
v2: fix define name, obey system lib default minimum version
v3: add error handling, fix bug in setting default minimum
src/openvpn/openssl_compat.h | 63 +++++++++++++++++++++++++++ src/openvpn/ssl.c | 5 ++- src/openvpn/ssl_backend.h | 4 +- src/openvpn/ssl_mbedtls.c | 3 +- src/openvpn/ssl_openssl.c | 100 +++++++++++++++++++++++++++---------------- 5 files changed, 136 insertions(+), 39 deletions(-)
src/openvpn/openssl_compat.h +63 -0
@@ -661,4 +661,67 @@ EC_GROUP_order_bits(const EC_GROUP *group)#define RSA_F_RSA_OSSL_PRIVATE_ENCRYPT RSA_F_RSA_EAY_PRIVATE_ENCRYPT#endif +#ifndef SSL_CTX_get_min_proto_version +/** Dummy SSL_CTX_get_min_proto_version for OpenSSL < 1.1 (not really needed) */ +static inline int +SSL_CTX_get_min_proto_version (SSL_CTX *ctx) +{ +return 0 ; +} +#endif /* SSL_CTX_get_min_proto_version */ + +#ifndef SSL_CTX_set_min_proto_version +/** Mimics SSL_CTX_set_min_proto_version for OpenSSL < 1.1 */ +static inline void +SSL_CTX_set_min_proto_version (SSL_CTX *ctx,long tls_ver_min) +{ +long sslopt = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;/* Never do < TLS 1.0 */ + +if (tls_ver_min >TLS1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1; + } +#ifdef SSL_OP_NO_TLSv1_1 +if (tls_ver_min >TLS1_1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_1; + } +#endif +#ifdef SSL_OP_NO_TLSv1_2 +if (tls_ver_min >TLS1_2_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_2; + } +#endif +SSL_CTX_set_options (ctx, sslopt); +} +#endif /* SSL_CTX_set_min_proto_version */ + +#ifndef SSL_CTX_set_max_proto_version +/** Mimics SSL_CTX_set_max_proto_version for OpenSSL < 1.1 */ +static inline void +SSL_CTX_set_max_proto_version (SSL_CTX *ctx,long tls_ver_max) +{ +long sslopt =0 ; + +if (tls_ver_max <TLS1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1; + } +#ifdef SSL_OP_NO_TLSv1_1 +if (tls_ver_max <TLS1_1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_1; + } +#endif +#ifdef SSL_OP_NO_TLSv1_2 +if (tls_ver_max <TLS1_2_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_2; + } +#endif +SSL_CTX_set_options (ctx, sslopt); +} +#endif /* SSL_CTX_set_max_proto_version */ +#endif /* OPENSSL_COMPAT_H_ */
src/openvpn/ssl.c +4 -1
@@ -622,7 +622,10 @@ init_ssl(const struct options *options, struct tls_root_ctx *new_ctx)* cipher restrictions before loading certificates */ tls_ctx_restrict_ciphers (new_ctx, options->cipher_list); -tls_ctx_set_options (new_ctx, options->ssl_flags); +if (!tls_ctx_set_options (new_ctx, options->ssl_flags)) + { + goto err; + }if (options->pkcs12_file) {
src/openvpn/ssl_backend.h +3 -1
@@ -162,8 +162,10 @@ bool tls_ctx_initialised(struct tls_root_ctx *ctx);* * @param ctx TLS context to set options on * @param ssl_flags SSL flags to set +* +* @return true on success, false otherwise. */ -void tls_ctx_set_options (struct tls_root_ctx *ctx,unsigned int ssl_flags); +bool tls_ctx_set_options (struct tls_root_ctx *ctx,unsigned int ssl_flags);/** * Restrict the list of ciphers that can be used within the TLS context.
src/openvpn/ssl_mbedtls.c +2 -1
@@ -206,9 +206,10 @@ key_state_export_keying_material(struct key_state_ssl *ssl, { } -void +bool tls_ctx_set_options (struct tls_root_ctx *ctx,unsigned int ssl_flags) { +return true; } static const char *
src/openvpn/ssl_openssl.c +64 -36
127 lines not on this page · raw message
Signature · 1 line
2.14.1
Hi,
Thanks for the v3.
All good except (sorry to say that :)
The compat versions of SSL_CTX_get_max_proto_version and its min counterpart should return a long or int not void. Assuming we want to continue supporting
openssl 1.0.
This was not an issue earlier when return value was not checked. Anyway, the correct
signature of the 1.1 functions (well macros) it replaces is long.
I should have pointed this out earlier...
There is one more thing that I'm not sure of. See below.
Quoted 40 lines · Steffan Karger
As described in <[email protected]...> on the openvpn-devel mailing list, --tls-version-min no longer works with OpenSSL 1.1. Kurt Roeckx posted in a debian bug report:
"This is marked as important because if you switch to openssl 1.1.0 the defaults minimum version in Debian is currently TLS 1.2 and you can't override it with the options that you're currently using (and are deprecated)."
This patch is loosely based on the original patch by Kurt, but solves the issue by adding functions to
openssl-compat.h, like we also did for all other openssl 1.1. breakage. This results in not having to add more ifdefs inssl_openssl.cand thus cleaner code.Signed-off-by Steffan Karger <[email protected]...>---
v2: fix define name, obey system lib default minimum version
v3: add error handling, fix bug in setting default minimumsrc/openvpn/openssl_compat.h | 63 +++++++++++++++++++++++++++ src/openvpn/ssl.c | 5 ++- src/openvpn/ssl_backend.h | 4 +- src/openvpn/ssl_mbedtls.c | 3 +- src/openvpn/ssl_openssl.c | 100 +++++++++++++++++++++++++++--- ------------- 5 files changed, 136 insertions(+), 39 deletions(-)src/openvpn/openssl_compat.h +2
-0@@ -661,4 +661,67 @@ EC_GROUP_order_bits(const EC_GROUP *group)#define RSA_F_RSA_OSSL_PRIVATE_ENCRYPT RSA_F_RSA_EAY_PRIVATE_ENCRYPT#endif +#ifndef SSL_CTX_get_min_proto_version +/** Dummy SSL_CTX_get_min_proto_version for OpenSSL < 1.1 (not really needed) */
src/openvpn/openssl_compat.h +1
-0+static inline int
src/openvpn/openssl_compat.h EC_GROUP_order_bits(const EC_GROUP *group) · line 676
Quoted 10 lines
src/openvpn/openssl_compat.h +10
-0+SSL_CTX_get_min_proto_version(SSL_CTX *ctx) +{ +return 0 ; +} +#endif /* SSL_CTX_get_min_proto_version */ + +#ifndef SSL_CTX_set_min_proto_version +/** Mimics SSL_CTX_set_min_proto_version for OpenSSL < 1.1 */ +static inline void +SSL_CTX_set_min_proto_version (SSL_CTX *ctx,long tls_ver_min)
static inline long (or int)
...
Quoted 12 lines
src/openvpn/openssl_compat.h +2
-0+{ +long sslopt = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;/* Never do < TLS 1.0 */
src/openvpn/openssl_compat.h +8
-0+ +if (tls_ver_min >TLS1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1; + } +#ifdef SSL_OP_NO_TLSv1_1 +if (tls_ver_min >TLS1_1_VERSION ) + {
src/openvpn/openssl_compat.h EC_GROUP_order_bits(const EC_GROUP *group) · line 696
Quoted 10 lines
src/openvpn/openssl_compat.h +10
-0+ sslopt |= SSL_OP_NO_TLSv1_1; + } +#endif +#ifdef SSL_OP_NO_TLSv1_2 +if (tls_ver_min >TLS1_2_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_2; + } +#endif +SSL_CTX_set_options (ctx, sslopt);
return 1;
src/openvpn/openssl_compat.h EC_GROUP_order_bits(const EC_GROUP *group) · line 703
Quoted 8 lines
src/openvpn/openssl_compat.h +7
-0+} +#endif /* SSL_CTX_set_min_proto_version */ + +#ifndef SSL_CTX_set_max_proto_version +/** Mimics SSL_CTX_set_max_proto_version for OpenSSL < 1.1 */ +static inline void +SSL_CTX_set_max_proto_version (SSL_CTX *ctx,long tls_ver_max)
static inline long (or int)
...
Quoted 11 lines
src/openvpn/openssl_compat.h +10
-0+{ +long sslopt =0 ; + +if (tls_ver_max <TLS1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1; + } +#ifdef SSL_OP_NO_TLSv1_1 +if (tls_ver_max <TLS1_1_VERSION ) + {
src/openvpn/openssl_compat.h EC_GROUP_order_bits(const EC_GROUP *group) · line 723
Quoted 10 lines
src/openvpn/openssl_compat.h +10
-0+ sslopt |= SSL_OP_NO_TLSv1_1; + } +#endif +#ifdef SSL_OP_NO_TLSv1_2 +if (tls_ver_max <TLS1_2_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_2; + } +#endif +SSL_CTX_set_options (ctx, sslopt);
return 1;
src/openvpn/openssl_compat.h EC_GROUP_order_bits(const EC_GROUP *group) · line 726
Quoted 4 lines
src/openvpn/openssl_compat.h +3
-0+} +#endif /* SSL_CTX_set_max_proto_version */ +
...
+/** Convert internal version number to openssl version number */
Quoted 7 lines
src/openvpn/openssl_compat.h +7
-0+static int +openssl_tls_version (int ver) +{ +if (ver ==TLS_VER_1_0 ) + { +return TLS1_VERSION ; + }
src/openvpn/openssl_compat.h
Quoted 10 lines
src/openvpn/openssl_compat.h +10
-0+else if (ver ==TLS_VER_1_1 ) + { +return TLS1_1_VERSION ; + } +else if (ver ==TLS_VER_1_2 ) + { +return TLS1_2_VERSION ; + } +return 0 ; +}
TLS1_2_VERSION may not be defined in openssl prior to 1.0.1, would it? Is that a problem? Do we still support 0.9.8 etc? I'm lazy to check this myself.
The rest is good.
Selva
Hi,
Quoted 9 lines · Selva Nair
Thanks for the v3.
All good except (sorry to say that :)
The compat versions of
SSL_CTX_get_max_proto_versionand its min counterpart should return a long or int not void. Assuming we want to continue supporting
openssl 1.0.
Quoted 5 lines
This was not an issue earlier when return value was not checked. Anyway, the correct
signature of the 1.1 functions (well macros) it replaces is long.I should have pointed this out earlier...
Gah, no, I should have thought about that before sending the patch. Not enough brains left on Friday night I guess... v4 coming.
Quoted 156 lines
There is one more thing that I'm not sure of. See below.
On Fri, Jan 19, 2018 at 2:22 PM, Steffan Karger <[email protected]... <mailto:[email protected]...>> wrote:
As described in <[email protected]... <mailto:[email protected]...>> on the openvpn-devel mailing list, --tls-version-min no longer works with OpenSSL 1.1. Kurt Roeckx posted in a debian bug report:
"This is marked as important because if you switch to openssl 1.1.0 the defaults minimum version in Debian is currently TLS 1.2 and you can't override it with the options that you're currently using (and are deprecated)."
This patch is loosely based on the original patch by Kurt, but solves the
issue by adding functions toopenssl-compat.h, like we also did for all other openssl 1.1. breakage. This results in not having to add more ifdefs
inssl_openssl.cand thus cleaner code.Signed-off-by Steffan Karger <[email protected]...<mailto:[email protected]...>>
---
v2: fix define name, obey system lib default minimum version
v3: add error handling, fix bug in setting default minimumsrc/openvpn/openssl_compat.h | 63 +++++++++++++++++++++++++++ src/openvpn/ssl.c | 5 ++- src/openvpn/ssl_backend.h | 4 +- src/openvpn/ssl_mbedtls.c | 3 +- src/openvpn/ssl_openssl.c | 100
+++++++++++++++++++++++++++----------------
5 files changed, 136 insertions(+), 39 deletions(-)diff --git
a/src/openvpn/openssl_compat.hb/src/openvpn/openssl_compat.hindex05ec4e95..4931fad3100644
---a/src/openvpn/openssl_compat.h
+++b/src/openvpn/openssl_compat.h
@@ -661,4 +661,67 @@EC_GROUP_order_bits(const EC_GROUP *group)#defineRSA_F_RSA_OSSL_PRIVATE_ENCRYPTRSA_F_RSA_EAY_PRIVATE_ENCRYPT
#endif+#ifndef
SSL_CTX_get_min_proto_version
+/** DummySSL_CTX_get_min_proto_versionfor OpenSSL < 1.1 (not really needed) */
+static inline int +SSL_CTX_get_min_proto_version(SSL_CTX *ctx)
+{
+ return 0;
+}
+#endif /*SSL_CTX_get_min_proto_version*/
+
+#ifndefSSL_CTX_set_min_proto_version
+/** MimicsSSL_CTX_set_min_proto_versionfor OpenSSL < 1.1 */ +static inline void +SSL_CTX_set_min_proto_version(SSL_CTX *ctx, longtls_ver_min)static inline long (or int)
...+{ + long sslopt = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; /* Never do < TLS 1.0 */ + + if (tls_ver_min > TLS1_VERSION) + { + sslopt |= SSL_OP_NO_TLSv1; + } +#ifdef SSL_OP_NO_TLSv1_1 + if (tls_ver_min > TLS1_1_VERSION) + { + sslopt |= SSL_OP_NO_TLSv1_1; + } +#endif +#ifdef SSL_OP_NO_TLSv1_2 + if (tls_ver_min > TLS1_2_VERSION) + { + sslopt |= SSL_OP_NO_TLSv1_2; + } +#endif + SSL_CTX_set_options(ctx, sslopt);return 1;
+}
+#endif /*SSL_CTX_set_min_proto_version*/
+
+#ifndefSSL_CTX_set_max_proto_version
+/** MimicsSSL_CTX_set_max_proto_versionfor OpenSSL < 1.1 */ +static inline void +SSL_CTX_set_max_proto_version(SSL_CTX *ctx, longtls_ver_max)static inline long (or int)
...+{ + long sslopt = 0; + + if (tls_ver_max < TLS1_VERSION) + { + sslopt |= SSL_OP_NO_TLSv1; + } +#ifdef SSL_OP_NO_TLSv1_1 + if (tls_ver_max < TLS1_1_VERSION) + { + sslopt |= SSL_OP_NO_TLSv1_1; + } +#endif +#ifdef SSL_OP_NO_TLSv1_2 + if (tls_ver_max < TLS1_2_VERSION) + { + sslopt |= SSL_OP_NO_TLSv1_2; + } +#endif + SSL_CTX_set_options(ctx, sslopt);return 1;
+} +#endif /* SSL_CTX_set_max_proto_version */0 +...
+/** Convert internal version number to openssl version number */ +static int +openssl_tls_version(int ver) +{ + if (ver == TLS_VER_1_0) + { + return TLS1_VERSION; + } + else if (ver == TLS_VER_1_1) + { + return TLS1_1_VERSION; + } + else if (ver == TLS_VER_1_2) + { + return TLS1_2_VERSION; + } + return 0; +}
Quoted 3 lines
TLS1_2_VERSIONmay not be defined in openssl prior to 1.0.1, would it? Is that a problem? Do we still support 0.9.8 etc? I'm lazy to check this myself.
The defines are already present in 0.9.8, and our master branch (which should get this patch first) only supports openssl 1.0.1 and newer. I'll need to double-check everything before cherry-picking to release/2.4 though. Let's first see if I can manage to send a correct patch for master...
Now testing the v4 against both 1.0.1 and 1.1.0, and will send to the ml soon.
Thanks!
-Steffan
PATCH v4 1/3 Fix --tls-version-min and --tls-version-max for OpenSSL 1.1+
In reply to Selva NairAs described in <[email protected]...> on the openvpn-devel mailing list, --tls-version-min no longer works with OpenSSL 1.1. Kurt Roeckx posted in a debian bug report:
"This is marked as important because if you switch to openssl 1.1.0 the defaults minimum version in Debian is currently TLS 1.2 and you can't override it with the options that you're currently using (and are deprecated)."
This patch is loosely based on the original patch by Kurt, but solves the issue by adding functions to openssl-compat.h, like we also did for all other openssl 1.1. breakage. This results in not having to add more ifdefs in ssl_openssl.c and thus cleaner code.
---
v2: fix define name, obey system lib default minimum version
v3: add error handling, fix bug in setting default minimum
v4: also update compat layer for v3 changes
src/openvpn/openssl_compat.h | 67 +++++++++++++++++++++++++++++ src/openvpn/ssl.c | 5 ++- src/openvpn/ssl_backend.h | 4 +- src/openvpn/ssl_mbedtls.c | 3 +- src/openvpn/ssl_openssl.c | 100 +++++++++++++++++++++++++++---------------- 5 files changed, 140 insertions(+), 39 deletions(-)
src/openvpn/openssl_compat.h +67 -0
@@ -661,4 +661,71 @@ EC_GROUP_order_bits(const EC_GROUP *group)#define RSA_F_RSA_OSSL_PRIVATE_ENCRYPT RSA_F_RSA_EAY_PRIVATE_ENCRYPT#endif +#ifndef SSL_CTX_get_min_proto_version +/** Dummy SSL_CTX_get_min_proto_version for OpenSSL < 1.1 (not really needed) */ +static inline int +SSL_CTX_get_min_proto_version (SSL_CTX *ctx) +{ +return 0 ; +} +#endif /* SSL_CTX_get_min_proto_version */ + +#ifndef SSL_CTX_set_min_proto_version +/** Mimics SSL_CTX_set_min_proto_version for OpenSSL < 1.1 */ +static inline int +SSL_CTX_set_min_proto_version (SSL_CTX *ctx,long tls_ver_min) +{ +long sslopt = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;/* Never do < TLS 1.0 */ + +if (tls_ver_min >TLS1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1; + } +#ifdef SSL_OP_NO_TLSv1_1 +if (tls_ver_min >TLS1_1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_1; + } +#endif +#ifdef SSL_OP_NO_TLSv1_2 +if (tls_ver_min >TLS1_2_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_2; + } +#endif +SSL_CTX_set_options (ctx, sslopt); + +return 1 ; +} +#endif /* SSL_CTX_set_min_proto_version */ + +#ifndef SSL_CTX_set_max_proto_version +/** Mimics SSL_CTX_set_max_proto_version for OpenSSL < 1.1 */ +static inline int +SSL_CTX_set_max_proto_version (SSL_CTX *ctx,long tls_ver_max) +{ +long sslopt =0 ; + +if (tls_ver_max <TLS1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1; + } +#ifdef SSL_OP_NO_TLSv1_1 +if (tls_ver_max <TLS1_1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_1; + } +#endif +#ifdef SSL_OP_NO_TLSv1_2 +if (tls_ver_max <TLS1_2_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_2; + } +#endif +SSL_CTX_set_options (ctx, sslopt); + +return 1 ; +} +#endif /* SSL_CTX_set_max_proto_version */ +#endif /* OPENSSL_COMPAT_H_ */
src/openvpn/ssl.c +4 -1
@@ -622,7 +622,10 @@ init_ssl(const struct options *options, struct tls_root_ctx *new_ctx)* cipher restrictions before loading certificates */ tls_ctx_restrict_ciphers (new_ctx, options->cipher_list); -tls_ctx_set_options (new_ctx, options->ssl_flags); +if (!tls_ctx_set_options (new_ctx, options->ssl_flags)) + { + goto err; + }if (options->pkcs12_file) {
src/openvpn/ssl_backend.h +3 -1
@@ -162,8 +162,10 @@ bool tls_ctx_initialised(struct tls_root_ctx *ctx);* * @param ctx TLS context to set options on * @param ssl_flags SSL flags to set +* +* @return true on success, false otherwise. */ -void tls_ctx_set_options (struct tls_root_ctx *ctx,unsigned int ssl_flags); +bool tls_ctx_set_options (struct tls_root_ctx *ctx,unsigned int ssl_flags);/** * Restrict the list of ciphers that can be used within the TLS context.
src/openvpn/ssl_mbedtls.c +2 -1
@@ -206,9 +206,10 @@ key_state_export_keying_material(struct key_state_ssl *ssl, { } -void +bool tls_ctx_set_options (struct tls_root_ctx *ctx,unsigned int ssl_flags) { +return true; } static const char *
src/openvpn/ssl_openssl.c +64 -36
127 lines not on this page · raw message
Signature · 1 line
2.14.1
Hi,
Thanks for last and final v4 :)
Quoted 297 lines · Steffan Karger
As described in <[email protected]...> on the openvpn-devel mailing list, --tls-version-min no longer works with OpenSSL 1.1. Kurt Roeckx posted in a debian bug report:
"This is marked as important because if you switch to openssl 1.1.0 the defaults minimum version in Debian is currently TLS 1.2 and you can't override it with the options that you're currently using (and are deprecated)."
This patch is loosely based on the original patch by Kurt, but solves the issue by adding functions to
openssl-compat.h, like we also did for all other openssl 1.1. breakage. This results in not having to add more ifdefs inssl_openssl.cand thus cleaner code.Signed-off-by Steffan Karger <[email protected]...>---
v2: fix define name, obey system lib default minimum version
v3: add error handling, fix bug in setting default minimum
v4: also update compat layer for v3 changessrc/openvpn/openssl_compat.h | 67 +++++++++++++++++++++++++++++ src/openvpn/ssl.c | 5 ++- src/openvpn/ssl_backend.h | 4 +- src/openvpn/ssl_mbedtls.c | 3 +- src/openvpn/ssl_openssl.c | 100 +++++++++++++++++++++++++++--- ------------- 5 files changed, 140 insertions(+), 39 deletions(-)src/openvpn/openssl_compat.h +2
-0@@ -661,4 +661,71 @@ EC_GROUP_order_bits(const EC_GROUP *group)#define RSA_F_RSA_OSSL_PRIVATE_ENCRYPT RSA_F_RSA_EAY_PRIVATE_ENCRYPT#endif +#ifndef SSL_CTX_get_min_proto_version +/** Dummy SSL_CTX_get_min_proto_version for OpenSSL < 1.1 (not really needed) */
src/openvpn/openssl_compat.h +13
-0+static inline int +SSL_CTX_get_min_proto_version (SSL_CTX *ctx) +{ +return 0 ; +} +#endif /* SSL_CTX_get_min_proto_version */ + +#ifndef SSL_CTX_set_min_proto_version +/** Mimics SSL_CTX_set_min_proto_version for OpenSSL < 1.1 */ +static inline int +SSL_CTX_set_min_proto_version (SSL_CTX *ctx,long tls_ver_min) +{ +long sslopt = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;/* Never do < TLS 1.0 */
src/openvpn/openssl_compat.h +52
-0+ +if (tls_ver_min >TLS1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1; + } +#ifdef SSL_OP_NO_TLSv1_1 +if (tls_ver_min >TLS1_1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_1; + } +#endif +#ifdef SSL_OP_NO_TLSv1_2 +if (tls_ver_min >TLS1_2_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_2; + } +#endif +SSL_CTX_set_options (ctx, sslopt); + +return 1 ; +} +#endif /* SSL_CTX_set_min_proto_version */ + +#ifndef SSL_CTX_set_max_proto_version +/** Mimics SSL_CTX_set_max_proto_version for OpenSSL < 1.1 */ +static inline int +SSL_CTX_set_max_proto_version (SSL_CTX *ctx,long tls_ver_max) +{ +long sslopt =0 ; + +if (tls_ver_max <TLS1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1; + } +#ifdef SSL_OP_NO_TLSv1_1 +if (tls_ver_max <TLS1_1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_1; + } +#endif +#ifdef SSL_OP_NO_TLSv1_2 +if (tls_ver_max <TLS1_2_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_2; + } +#endif +SSL_CTX_set_options (ctx, sslopt); + +return 1 ; +} +#endif /* SSL_CTX_set_max_proto_version */ +#endif /* OPENSSL_COMPAT_H_ */ src/openvpn/ssl.c +4
-1@@ -622,7 +622,10 @@ init_ssl(const struct options *options, structtls_root_ctx *new_ctx) * cipher restrictions before loading certificates */ tls_ctx_restrict_ciphers (new_ctx, options->cipher_list); -tls_ctx_set_options (new_ctx, options->ssl_flags); +if (!tls_ctx_set_options (new_ctx, options->ssl_flags)) + { + goto err; + }if (options->pkcs12_file){src/openvpn/ssl_backend.h +3
-1@@ -162,8 +162,10 @@ bool tls_ctx_initialised(struct tls_root_ctx *ctx);* * @param ctx TLS context to set options on * @param ssl_flags SSL flags to set +* +* @return true on success, false otherwise. */ -void tls_ctx_set_options (struct tls_root_ctx *ctx,unsigned int ssl_flags); +bool tls_ctx_set_options (struct tls_root_ctx *ctx,unsigned int ssl_flags);/**
* Restrict the list of ciphers that can be used within the TLS context.src/openvpn/ssl_mbedtls.c +2
-1@@ -206,9 +206,10 @@ key_state_export_keying_material(struct key_state_ssl *ssl, { } -void +bool tls_ctx_set_options (struct tls_root_ctx *ctx,unsigned int ssl_flags) { +return true; }static const char *
src/openvpn/ssl_openssl.c +28
-3@@ -206,16 +206,65 @@ info_callback(INFO_CALLBACK_SSL_CONST SSL *s, int where, int ret)int tls_version_max (void ) { -#if defined(SSL_OP_NO_TLSv1_2) +#if defined(TLS1_2_VERSION ) || defined(SSL_OP_NO_TLSv1_2)return TLS_VER_1_2 ; -#elif defined(SSL_OP_NO_TLSv1_1) +#elif defined(TLS1_1_VERSION ) || defined(SSL_OP_NO_TLSv1_1)return TLS_VER_1_1 ;#else return TLS_VER_1_0 ;#endif } -void +/** Convert internal version number to openssl version number */ +static int +openssl_tls_version (int ver) +{ +if (ver ==TLS_VER_1_0 ) + { +return TLS1_VERSION ; + } +else if (ver ==TLS_VER_1_1 ) + { +return TLS1_1_VERSION ; + } +else if (ver ==TLS_VER_1_2 ) + { +return TLS1_2_VERSION ; + } +return 0 ; +} + +static bool +tls_ctx_set_tls_versions (struct tls_root_ctx *ctx,unsigned int ssl_flags) +{ +int tls_ver_min =openssl_tls_version ( + (ssl_flags >>SSLF_TLS_VERSION_MIN_SHIFT ) &SSLF_TLS_VERSION_MIN_MASK ); + int tls_ver_max = openssl_tls_version( + (ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) &
SSLF_TLS_VERSION_MAX_MASK);src/openvpn/ssl_openssl.c +11
-0+ +if (!tls_ver_min) + { +/* Enforce at least TLS 1.0 */ +int cur_min =SSL_CTX_get_min_proto_version (ctx->ctx); + tls_ver_min = cur_min <TLS1_VERSION ?TLS1_VERSION : cur_min; + } + +if (!SSL_CTX_set_min_proto_version (ctx->ctx, tls_ver_min)) + { + msg(D_TLS_ERRORS, "%s: failed to set minimum TLS version",
__func__);src/openvpn/ssl_openssl.c +4
-0+return false; + } + + if (tls_ver_max && !SSL_CTX_set_max_proto_version(ctx->ctx,
tls_ver_max))src/openvpn/ssl_openssl.c +2
-0+ { + msg(D_TLS_ERRORS, "%s: failed to set maximum TLS version",
__func__);src/openvpn/ssl_openssl.c +7
-1+return false; + } + +return true; +} + +bool tls_ctx_set_options (struct tls_root_ctx *ctx,unsigned int ssl_flags) {ASSERT (NULL != ctx);@@ -223,41 +272,18 @@ tls_ctx_set_options(struct tls_root_ctx *ctx, unsigned int ssl_flags)/* default certificate verification flags */ int flags =SSL_VERIFY_PEER |SSL_VERIFY_FAIL_IF_NO_PEER_CERT ; -/* process SSL options including minimum TLS version we will accept from peer */
src/openvpn/ssl_openssl.c +0
-2- { - long sslopt = SSL_OP_SINGLE_DH_USE | SSL_OP_NO_TICKET |
SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3;src/openvpn/ssl_openssl.c +0
-3-int tls_ver_max =TLS_VER_UNSPEC ; -const int tls_ver_min = - (ssl_flags >> SSLF_TLS_VERSION_MIN_SHIFT) &
SSLF_TLS_VERSION_MIN_MASK;src/openvpn/ssl_openssl.c +0
-3- - tls_ver_max = - (ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) &
SSLF_TLS_VERSION_MAX_MASK;src/openvpn/ssl_openssl.c +10
-24-if (tls_ver_max <=TLS_VER_UNSPEC ) - { - tls_ver_max =tls_version_max (); - } - -if (tls_ver_min >TLS_VER_1_0 || tls_ver_max <TLS_VER_1_0 ) - { - sslopt |= SSL_OP_NO_TLSv1; - } -#ifdef SSL_OP_NO_TLSv1_1 -if (tls_ver_min >TLS_VER_1_1 || tls_ver_max <TLS_VER_1_1 ) - { - sslopt |= SSL_OP_NO_TLSv1_1; - } -#endif -#ifdef SSL_OP_NO_TLSv1_2 -if (tls_ver_min >TLS_VER_1_2 || tls_ver_max <TLS_VER_1_2 ) - { - sslopt |= SSL_OP_NO_TLSv1_2; - } -#endif +/* process SSL options */ +long sslopt =SSL_OP_SINGLE_DH_USE |SSL_OP_NO_TICKET ;#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE - sslopt |=SSL_OP_CIPHER_SERVER_PREFERENCE ; + sslopt |=SSL_OP_CIPHER_SERVER_PREFERENCE ;#endif - sslopt |=SSL_OP_NO_COMPRESSION ; -SSL_CTX_set_options (ctx->ctx, sslopt); + sslopt |=SSL_OP_NO_COMPRESSION ; + +SSL_CTX_set_options (ctx->ctx, sslopt); + +if (!tls_ctx_set_tls_versions (ctx, ssl_flags)) + { +return false; }#ifdef SSL_MODE_RELEASE_BUFFERS
src/openvpn/ssl_openssl.c tls_ctx_set_options(struct tls_root_ctx *ctx, unsigned · line 313
Quoted 8 lines
src/openvpn/ssl_openssl.c +2
-0@@ -280,6 +306,8 @@ tls_ctx_set_options(struct tls_root_ctx *ctx, unsigned int ssl_flags) SSL_CTX_set_verify(ctx->ctx, flags, verify_callback);SSL_CTX_set_info_callback (ctx->ctx, info_callback); + +return true; }
Now I can tease patchwork by
Selva
fragmentux
Tested-by Richard Bonhommehello
Quoted 314 lines · Selva Nair
Hi,
Thanks for last and final v4 :)
Quoted 297 lines · Steffan Karger
As described in <[email protected]...> on the openvpn-devel mailing list, --tls-version-min no longer works with OpenSSL 1.1. Kurt Roeckx posted in a debian bug report:
"This is marked as important because if you switch to openssl 1.1.0 the defaults minimum version in Debian is currently TLS 1.2 and you can't override it with the options that you're currently using (and are deprecated)."
This patch is loosely based on the original patch by Kurt, but solves the issue by adding functions to
openssl-compat.h, like we also did for all other openssl 1.1. breakage. This results in not having to add more ifdefs inssl_openssl.cand thus cleaner code.Signed-off-by Steffan Karger <[email protected]...>---
v2: fix define name, obey system lib default minimum version
v3: add error handling, fix bug in setting default minimum
v4: also update compat layer for v3 changessrc/openvpn/openssl_compat.h | 67 +++++++++++++++++++++++++++++ src/openvpn/ssl.c | 5 ++- src/openvpn/ssl_backend.h | 4 +- src/openvpn/ssl_mbedtls.c | 3 +- src/openvpn/ssl_openssl.c | 100 +++++++++++++++++++++++++++--- ------------- 5 files changed, 140 insertions(+), 39 deletions(-)src/openvpn/openssl_compat.h +2
-0@@ -661,4 +661,71 @@ EC_GROUP_order_bits(const EC_GROUP *group)#define RSA_F_RSA_OSSL_PRIVATE_ENCRYPT RSA_F_RSA_EAY_PRIVATE_ENCRYPT#endif +#ifndef SSL_CTX_get_min_proto_version +/** Dummy SSL_CTX_get_min_proto_version for OpenSSL < 1.1 (not really needed) */
src/openvpn/openssl_compat.h +13
-0+static inline int +SSL_CTX_get_min_proto_version (SSL_CTX *ctx) +{ +return 0 ; +} +#endif /* SSL_CTX_get_min_proto_version */ + +#ifndef SSL_CTX_set_min_proto_version +/** Mimics SSL_CTX_set_min_proto_version for OpenSSL < 1.1 */ +static inline int +SSL_CTX_set_min_proto_version (SSL_CTX *ctx,long tls_ver_min) +{ +long sslopt = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;/* Never do < TLS 1.0 */
src/openvpn/openssl_compat.h +52
-0+ +if (tls_ver_min >TLS1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1; + } +#ifdef SSL_OP_NO_TLSv1_1 +if (tls_ver_min >TLS1_1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_1; + } +#endif +#ifdef SSL_OP_NO_TLSv1_2 +if (tls_ver_min >TLS1_2_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_2; + } +#endif +SSL_CTX_set_options (ctx, sslopt); + +return 1 ; +} +#endif /* SSL_CTX_set_min_proto_version */ + +#ifndef SSL_CTX_set_max_proto_version +/** Mimics SSL_CTX_set_max_proto_version for OpenSSL < 1.1 */ +static inline int +SSL_CTX_set_max_proto_version (SSL_CTX *ctx,long tls_ver_max) +{ +long sslopt =0 ; + +if (tls_ver_max <TLS1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1; + } +#ifdef SSL_OP_NO_TLSv1_1 +if (tls_ver_max <TLS1_1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_1; + } +#endif +#ifdef SSL_OP_NO_TLSv1_2 +if (tls_ver_max <TLS1_2_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_2; + } +#endif +SSL_CTX_set_options (ctx, sslopt); + +return 1 ; +} +#endif /* SSL_CTX_set_max_proto_version */ +#endif /* OPENSSL_COMPAT_H_ */ src/openvpn/ssl.c +4
-1@@ -622,7 +622,10 @@ init_ssl(const struct options *options, structtls_root_ctx *new_ctx) * cipher restrictions before loading certificates */ tls_ctx_restrict_ciphers (new_ctx, options->cipher_list); -tls_ctx_set_options (new_ctx, options->ssl_flags); +if (!tls_ctx_set_options (new_ctx, options->ssl_flags)) + { + goto err; + }if (options->pkcs12_file){src/openvpn/ssl_backend.h +3
-1@@ -162,8 +162,10 @@ bool tls_ctx_initialised(struct tls_root_ctx *ctx);* * @param ctx TLS context to set options on * @param ssl_flags SSL flags to set +* +* @return true on success, false otherwise. */ -void tls_ctx_set_options (struct tls_root_ctx *ctx,unsigned int ssl_flags); +bool tls_ctx_set_options (struct tls_root_ctx *ctx,unsigned int ssl_flags);/**
* Restrict the list of ciphers that can be used within the TLS context.src/openvpn/ssl_mbedtls.c +2
-1@@ -206,9 +206,10 @@ key_state_export_keying_material(struct key_state_ssl *ssl, { } -void +bool tls_ctx_set_options (struct tls_root_ctx *ctx,unsigned int ssl_flags) { +return true; }static const char *
src/openvpn/ssl_openssl.c +28
-3@@ -206,16 +206,65 @@ info_callback(INFO_CALLBACK_SSL_CONST SSL *s, int where, int ret)int tls_version_max (void ) { -#if defined(SSL_OP_NO_TLSv1_2) +#if defined(TLS1_2_VERSION ) || defined(SSL_OP_NO_TLSv1_2)return TLS_VER_1_2 ; -#elif defined(SSL_OP_NO_TLSv1_1) +#elif defined(TLS1_1_VERSION ) || defined(SSL_OP_NO_TLSv1_1)return TLS_VER_1_1 ;#else return TLS_VER_1_0 ;#endif } -void +/** Convert internal version number to openssl version number */ +static int +openssl_tls_version (int ver) +{ +if (ver ==TLS_VER_1_0 ) + { +return TLS1_VERSION ; + } +else if (ver ==TLS_VER_1_1 ) + { +return TLS1_1_VERSION ; + } +else if (ver ==TLS_VER_1_2 ) + { +return TLS1_2_VERSION ; + } +return 0 ; +} + +static bool +tls_ctx_set_tls_versions (struct tls_root_ctx *ctx,unsigned int ssl_flags) +{ +int tls_ver_min =openssl_tls_version ( + (ssl_flags >>SSLF_TLS_VERSION_MIN_SHIFT ) &SSLF_TLS_VERSION_MIN_MASK ); + int tls_ver_max = openssl_tls_version( + (ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) &
SSLF_TLS_VERSION_MAX_MASK);src/openvpn/ssl_openssl.c +11
-0+ +if (!tls_ver_min) + { +/* Enforce at least TLS 1.0 */ +int cur_min =SSL_CTX_get_min_proto_version (ctx->ctx); + tls_ver_min = cur_min <TLS1_VERSION ?TLS1_VERSION : cur_min; + } + +if (!SSL_CTX_set_min_proto_version (ctx->ctx, tls_ver_min)) + { + msg(D_TLS_ERRORS, "%s: failed to set minimum TLS version",
__func__);src/openvpn/ssl_openssl.c +4
-0+return false; + } + + if (tls_ver_max && !SSL_CTX_set_max_proto_version(ctx->ctx,
tls_ver_max))src/openvpn/ssl_openssl.c +2
-0+ { + msg(D_TLS_ERRORS, "%s: failed to set maximum TLS version",
__func__);src/openvpn/ssl_openssl.c +7
-1+return false; + } + +return true; +} + +bool tls_ctx_set_options (struct tls_root_ctx *ctx,unsigned int ssl_flags) {ASSERT (NULL != ctx);@@ -223,41 +272,18 @@ tls_ctx_set_options(struct tls_root_ctx *ctx, unsigned int ssl_flags)/* default certificate verification flags */ int flags =SSL_VERIFY_PEER |SSL_VERIFY_FAIL_IF_NO_PEER_CERT ; -/* process SSL options including minimum TLS version we will accept from peer */
src/openvpn/ssl_openssl.c +0
-2- { - long sslopt = SSL_OP_SINGLE_DH_USE | SSL_OP_NO_TICKET |
SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3;src/openvpn/ssl_openssl.c +0
-3-int tls_ver_max =TLS_VER_UNSPEC ; -const int tls_ver_min = - (ssl_flags >> SSLF_TLS_VERSION_MIN_SHIFT) &
SSLF_TLS_VERSION_MIN_MASK;src/openvpn/ssl_openssl.c +0
-3- - tls_ver_max = - (ssl_flags >> SSLF_TLS_VERSION_MAX_SHIFT) &
SSLF_TLS_VERSION_MAX_MASK;src/openvpn/ssl_openssl.c +10
-24-if (tls_ver_max <=TLS_VER_UNSPEC ) - { - tls_ver_max =tls_version_max (); - } - -if (tls_ver_min >TLS_VER_1_0 || tls_ver_max <TLS_VER_1_0 ) - { - sslopt |= SSL_OP_NO_TLSv1; - } -#ifdef SSL_OP_NO_TLSv1_1 -if (tls_ver_min >TLS_VER_1_1 || tls_ver_max <TLS_VER_1_1 ) - { - sslopt |= SSL_OP_NO_TLSv1_1; - } -#endif -#ifdef SSL_OP_NO_TLSv1_2 -if (tls_ver_min >TLS_VER_1_2 || tls_ver_max <TLS_VER_1_2 ) - { - sslopt |= SSL_OP_NO_TLSv1_2; - } -#endif +/* process SSL options */ +long sslopt =SSL_OP_SINGLE_DH_USE |SSL_OP_NO_TICKET ;#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE - sslopt |=SSL_OP_CIPHER_SERVER_PREFERENCE ; + sslopt |=SSL_OP_CIPHER_SERVER_PREFERENCE ;#endif - sslopt |=SSL_OP_NO_COMPRESSION ; -SSL_CTX_set_options (ctx->ctx, sslopt); + sslopt |=SSL_OP_NO_COMPRESSION ; + +SSL_CTX_set_options (ctx->ctx, sslopt); + +if (!tls_ctx_set_tls_versions (ctx, ssl_flags)) + { +return false; }#ifdef SSL_MODE_RELEASE_BUFFERS src/openvpn/ssl_openssl.c tls_ctx_set_options(struct tls_root_ctx *ctx, unsigned · line 313
Quoted 8 lines
src/openvpn/ssl_openssl.c +2
-0@@ -280,6 +306,8 @@ tls_ctx_set_options(struct tls_root_ctx *ctx, unsigned int ssl_flags) SSL_CTX_set_verify(ctx->ctx, flags, verify_callback);SSL_CTX_set_info_callback (ctx->ctx, info_callback); + +return true; }Now I can tease patchwork by
Quoted 4 lines
Acked-by Selva Nair <[email protected]...>Reviewed-by Selva Nair <[email protected]...>Tested-by Selva Nair <[email protected]...>
Purely to see what patchworks makes of this (i did what i could)
Also
PATCH 1/1 Fix --tls-version-min and --tls-version-max for OpenSSL 1.1+
In reply to Steffan KargerAs described in <[email protected]...> on the openvpn-devel mailing list, --tls-version-min no longer works with OpenSSL 1.1. Kurt Roeckx posted in a debian bug report:
"This is marked as important because if you switch to openssl 1.1.0 the defaults minimum version in Debian is currently TLS 1.2 and you can't override it with the options that you're currently using (and are deprecated)."
This patch is loosely based on the original patch by Kurt, but solves the issue by adding functions to openssl-compat.h, like we also did for all other openssl 1.1. breakage. This results in not having to add more ifdefs in ssl_openssl.c and thus cleaner code.
---
Note: This is cherry-pick to release/2.4 of the v4 patch for master.
Tested to compile and work against OpenSSL 0.9.8 (for as far as possible; 0.9.8 only does TLS 1.0).
src/openvpn/openssl_compat.h | 67 ++++++++++++++++++++++++++++ src/openvpn/ssl.c | 5 ++- src/openvpn/ssl_backend.h | 4 +- src/openvpn/ssl_mbedtls.c | 3 +- src/openvpn/ssl_openssl.c | 102 +++++++++++++++++++++++++++---------------- 5 files changed, 141 insertions(+), 40 deletions(-)
src/openvpn/openssl_compat.h +67 -0
@@ -661,4 +661,71 @@ EC_GROUP_order_bits(const EC_GROUP *group)#define RSA_F_RSA_OSSL_PRIVATE_ENCRYPT RSA_F_RSA_EAY_PRIVATE_ENCRYPT#endif +#ifndef SSL_CTX_get_min_proto_version +/** Dummy SSL_CTX_get_min_proto_version for OpenSSL < 1.1 (not really needed) */ +static inline int +SSL_CTX_get_min_proto_version (SSL_CTX *ctx) +{ +return 0 ; +} +#endif /* SSL_CTX_get_min_proto_version */ + +#ifndef SSL_CTX_set_min_proto_version +/** Mimics SSL_CTX_set_min_proto_version for OpenSSL < 1.1 */ +static inline int +SSL_CTX_set_min_proto_version (SSL_CTX *ctx,long tls_ver_min) +{ +long sslopt = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;/* Never do < TLS 1.0 */ + +if (tls_ver_min >TLS1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1; + } +#ifdef SSL_OP_NO_TLSv1_1 +if (tls_ver_min >TLS1_1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_1; + } +#endif +#ifdef SSL_OP_NO_TLSv1_2 +if (tls_ver_min >TLS1_2_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_2; + } +#endif +SSL_CTX_set_options (ctx, sslopt); + +return 1 ; +} +#endif /* SSL_CTX_set_min_proto_version */ + +#ifndef SSL_CTX_set_max_proto_version +/** Mimics SSL_CTX_set_max_proto_version for OpenSSL < 1.1 */ +static inline int +SSL_CTX_set_max_proto_version (SSL_CTX *ctx,long tls_ver_max) +{ +long sslopt =0 ; + +if (tls_ver_max <TLS1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1; + } +#ifdef SSL_OP_NO_TLSv1_1 +if (tls_ver_max <TLS1_1_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_1; + } +#endif +#ifdef SSL_OP_NO_TLSv1_2 +if (tls_ver_max <TLS1_2_VERSION ) + { + sslopt |= SSL_OP_NO_TLSv1_2; + } +#endif +SSL_CTX_set_options (ctx, sslopt); + +return 1 ; +} +#endif /* SSL_CTX_set_max_proto_version */ +#endif /* OPENSSL_COMPAT_H_ */
src/openvpn/ssl.c +4 -1
@@ -624,7 +624,10 @@ init_ssl(const struct options *options, struct tls_root_ctx *new_ctx)* cipher restrictions before loading certificates */ tls_ctx_restrict_ciphers (new_ctx, options->cipher_list); -tls_ctx_set_options (new_ctx, options->ssl_flags); +if (!tls_ctx_set_options (new_ctx, options->ssl_flags)) + { + goto err; + }if (options->pkcs12_file) {
src/openvpn/ssl_backend.h +3 -1
@@ -164,8 +164,10 @@ bool tls_ctx_initialised(struct tls_root_ctx *ctx);* * @param ctx TLS context to set options on * @param ssl_flags SSL flags to set +* +* @return true on success, false otherwise. */ -void tls_ctx_set_options (struct tls_root_ctx *ctx,unsigned int ssl_flags); +bool tls_ctx_set_options (struct tls_root_ctx *ctx,unsigned int ssl_flags);/** * Restrict the list of ciphers that can be used within the TLS context.
src/openvpn/ssl_mbedtls.c +2 -1
@@ -206,9 +206,10 @@ key_state_export_keying_material(struct key_state_ssl *ssl, { } -void +bool tls_ctx_set_options (struct tls_root_ctx *ctx,unsigned int ssl_flags) { +return true; } static const char *
src/openvpn/ssl_openssl.c +65 -37
131 lines not on this page · raw message
Signature · 1 line
2.14.1
ACK (compared the patches, only difference is the SSL_OP_NO_COMPRESSION #ifdef). So I take the ACK from Selva, on the base patch, and add my ACK for "the 2.4 modifications make sense". Haven't tested on an 0.9.8 system yet.
for patchwork:
Your patch has been applied to the release/2.4 branch.
commit a25a278c1ccdbfd9ca06f60f2cc4cf2436269854
Author: Steffan Karger Date: Sat Jan 20 10:42:28 2018 +0100
Fix --tls-version-min and --tls-version-max for OpenSSL 1.1+
Signed-off-by: Steffan Karger <[email protected]...>
Acked-by: Selva Nair <[email protected]...>
Acked-by: Gert Doering <[email protected]...>
Message-Id: <[email protected]...>
URL: https://www.mail-archive.com/search?l=mid&[email protected]...
Signed-off-by: Gert Doering <[email protected]...>
(cherry picked with 2.4 amendments from commit 0e8a30c0b05c1e2b59a1dea0a6eab5daa1d9d9a1)--
kind regards,
Gert Doering
Your patch has been applied to the master branch.
I have added a pointer to the Debian bug report for completeness.
commit 0e8a30c0b05c1e2b59a1dea0a6eab5daa1d9d9a1
Author: Steffan Karger Date: Fri Jan 19 22:27:21 2018 +0100
Fix --tls-version-min and --tls-version-max for OpenSSL 1.1+
Signed-off-by: Steffan Karger <[email protected]...>
Acked-by: Selva Nair <[email protected]...>
Message-Id: <[email protected]...>
URL: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=873302
URL: https://www.mail-archive.com/[email protected]/msg16284.html
Signed-off-by: Gert Doering <[email protected]...>--
kind regards,
Gert Doering