Re: State of 0-RTT TLS resumption with OpenSSL
On Wed, Jan 09, 2019 at 04:21:03PM +0100, Olivier Houchard wrote: > Can you push the attached patches ? Sure, now done, thanks! Willy
Re: State of 0-RTT TLS resumption with OpenSSL
Hi Willy, On Tue, Jan 08, 2019 at 03:44:07PM +0100, Willy Tarreau wrote: > On Tue, Jan 08, 2019 at 03:27:58PM +0100, Olivier Houchard wrote: > > On Tue, Jan 08, 2019 at 03:00:32PM +0100, Janusz Dziemidowicz wrote: > > > pt., 4 sty 2019 o 11:59 Olivier Houchard > > > napisa??(a): > > > However, I believe in general this is a bit more complicated. RFC 8446 > > > described this in detail in section 8: > > > https://tools.ietf.org/html/rfc8446#section-8 > > > My understanding is that RFC highly recommends anti-replay with 0-RTT. > > > It seems that s_server implements single use tickets, which is exactly > > > what is in section 8.1. The above patch disables anti-replay > > > completely in haproxy, which might warrant some updates to > > > documentation about allow-0rtt option? > > > > > > > Hi Janusz, > > > > Yes indeed, I thought I documented it better than that, but obviously I > > didn't :) > > The allow-0rtt option was added before OpenSSL added anti-replay protection, > > and I'm pretty sure the RFC wasn't talking about it yet, it was mostly > > saying > > it was a security concern, so it was designed with "only allow it for what > > would be safe to replay", and the documentation should certainly reflect > > that. > > I will make it explicit. > > > > Thanks a lot ! > > To clear some of the confusion on this subject, when 0-RTT was designed > in TLS 1.3, it was sort of a backport from QUIC, and it was decided that > the replay protection was up to the application layer (here "application" > is not in the sense of the web application you're using, but the HTTP layer > on top of TLS). And RFC8470 (https://tools.ietf.org/html/rfc8470), which > haproxy implements, was produced exactly to address this specific area. > > Thus an HTTP implementation which properly implements RFC8470 does have > TLS anti-replay covered by the application layer. > Can you push the attached patches ? Thanks ! Olivier >From fe291b43e1cb9143edf0051a1d69247dde298118 Mon Sep 17 00:00:00 2001 From: Olivier Houchard Date: Wed, 2 Jan 2019 18:46:41 +0100 Subject: [PATCH 1/2] BUG/MEDIUM: ssl: Disable anti-replay protection and set max data with 0RTT. When using early data, disable the OpenSSL anti-replay protection, and set the max amount of early data we're ready to accept, based on the size of buffers, or early data won't work with the released OpenSSL 1.1.1. This should be backported to 1.8. --- src/ssl_sock.c | 4 1 file changed, 4 insertions(+) diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 282b85dd..13ce2e5b 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -3869,6 +3869,10 @@ ssl_sock_initial_ctx(struct bind_conf *bind_conf) SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk); SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk); #elif (OPENSSL_VERSION_NUMBER >= 0x10101000L) + if (bind_conf->ssl_conf.early_data) { + SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY); + SSL_CTX_set_max_early_data(ctx, global.tune.bufsize - global.tune.maxrewrite); + } SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL); SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk); #else -- 2.14.4 >From c1105e9723a2c79e3b445287586350e0d3d3e291 Mon Sep 17 00:00:00 2001 From: Olivier Houchard Date: Tue, 8 Jan 2019 15:35:32 +0100 Subject: [PATCH 2/2] DOC: Be a bit more explicit about allow-0rtt security implications. Document a bit better than allow-0rtt can trivially be used for replay attacks, and so should only be used when it's safe to replay a request. This should probably be backported to 1.8 and 1.9. --- doc/configuration.txt | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index 2447254c..888515fb 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -10768,7 +10768,10 @@ accept-proxy allow-0rtt Allow receiving early data when using TLSv1.3. This is disabled by default, - due to security considerations. + due to security considerations. Because it is vulnerable to replay attacks, + you should only allow if for requests that are safe to replay, ie requests + that are idempotent. You can use the "wait-for-handshake" action for any + request that wouldn't be safe with early data. alpn This enables the TLS ALPN extension and advertises the specified protocol -- 2.14.4
Re: State of 0-RTT TLS resumption with OpenSSL
On Tue, Jan 08, 2019 at 03:27:58PM +0100, Olivier Houchard wrote: > On Tue, Jan 08, 2019 at 03:00:32PM +0100, Janusz Dziemidowicz wrote: > > pt., 4 sty 2019 o 11:59 Olivier Houchard > > napisa??(a): > > However, I believe in general this is a bit more complicated. RFC 8446 > > described this in detail in section 8: > > https://tools.ietf.org/html/rfc8446#section-8 > > My understanding is that RFC highly recommends anti-replay with 0-RTT. > > It seems that s_server implements single use tickets, which is exactly > > what is in section 8.1. The above patch disables anti-replay > > completely in haproxy, which might warrant some updates to > > documentation about allow-0rtt option? > > > > Hi Janusz, > > Yes indeed, I thought I documented it better than that, but obviously I > didn't :) > The allow-0rtt option was added before OpenSSL added anti-replay protection, > and I'm pretty sure the RFC wasn't talking about it yet, it was mostly saying > it was a security concern, so it was designed with "only allow it for what > would be safe to replay", and the documentation should certainly reflect that. > I will make it explicit. > > Thanks a lot ! To clear some of the confusion on this subject, when 0-RTT was designed in TLS 1.3, it was sort of a backport from QUIC, and it was decided that the replay protection was up to the application layer (here "application" is not in the sense of the web application you're using, but the HTTP layer on top of TLS). And RFC8470 (https://tools.ietf.org/html/rfc8470), which haproxy implements, was produced exactly to address this specific area. Thus an HTTP implementation which properly implements RFC8470 does have TLS anti-replay covered by the application layer. Hoping this helps, Willy
Re: State of 0-RTT TLS resumption with OpenSSL
On Tue, Jan 08, 2019 at 03:00:32PM +0100, Janusz Dziemidowicz wrote: > pt., 4 sty 2019 o 11:59 Olivier Houchard napisa??(a): > > I understand the concern. > > I checked and both nghttp2 and nginx disable the replay protection. The idea > > is you're supposed to allow early data only on harmless requests anyway, ie > > ones that could be replayed with no consequence. > > Sorry for the late reply, I was pondering the problem ;) I'm pretty ok > with this patch, especially since others seem to do the same. And my > use case is DNS-over-TLS, which has no problems with replays anyway ;) > > However, I believe in general this is a bit more complicated. RFC 8446 > described this in detail in section 8: > https://tools.ietf.org/html/rfc8446#section-8 > My understanding is that RFC highly recommends anti-replay with 0-RTT. > It seems that s_server implements single use tickets, which is exactly > what is in section 8.1. The above patch disables anti-replay > completely in haproxy, which might warrant some updates to > documentation about allow-0rtt option? > Hi Janusz, Yes indeed, I thought I documented it better than that, but obviously I didn't :) The allow-0rtt option was added before OpenSSL added anti-replay protection, and I'm pretty sure the RFC wasn't talking about it yet, it was mostly saying it was a security concern, so it was designed with "only allow it for what would be safe to replay", and the documentation should certainly reflect that. I will make it explicit. Thanks a lot ! Olivier
Re: State of 0-RTT TLS resumption with OpenSSL
pt., 4 sty 2019 o 11:59 Olivier Houchard napisał(a): > I understand the concern. > I checked and both nghttp2 and nginx disable the replay protection. The idea > is you're supposed to allow early data only on harmless requests anyway, ie > ones that could be replayed with no consequence. Sorry for the late reply, I was pondering the problem ;) I'm pretty ok with this patch, especially since others seem to do the same. And my use case is DNS-over-TLS, which has no problems with replays anyway ;) However, I believe in general this is a bit more complicated. RFC 8446 described this in detail in section 8: https://tools.ietf.org/html/rfc8446#section-8 My understanding is that RFC highly recommends anti-replay with 0-RTT. It seems that s_server implements single use tickets, which is exactly what is in section 8.1. The above patch disables anti-replay completely in haproxy, which might warrant some updates to documentation about allow-0rtt option? -- Janusz Dziemidowicz
Re: State of 0-RTT TLS resumption with OpenSSL
Hi Janusz, On Fri, Jan 04, 2019 at 10:53:51AM +0100, Janusz Dziemidowicz wrote: > czw., 3 sty 2019 o 17:52 Olivier Houchard napisa??(a): > > Ah I think I figured it out. > > OpenSSL added anti-replay protection when using early data, and it messes up > > with the session handling. > > With the updated attached patch, I get early data to work again. Is it > > better > > for you ? > > Now it works. > However, I am a bit concerned about disabling something that sounds > like an important safeguard. > Reading this > https://www.openssl.org/docs/man1.1.1/man3/SSL_SESSION_get_max_early_data.html#REPLAY-PROTECTION > suggests that it is really not a wise thing to do. > > And again, s_server works differently. It does not use > SSL_OP_NO_ANTI_REPLAY but the resumption, with early data, works, > once. Then you get new session that you can resume again if you wish, > but also once. You cannot resume the same session twice. With your > patch I can resume single session as many times as I wish. Coupled > with early data this is exactly something that TLS 1.3 RFC warns > against. This probably is due to haproxy using external session > management. > > I'll try to dig more into this on weekend, now that I know where to look. > I understand the concern. I checked and both nghttp2 and nginx disable the replay protection. The idea is you're supposed to allow early data only on harmless requests anyway, ie ones that could be replayed with no consequence. Regards, Olivier
Re: State of 0-RTT TLS resumption with OpenSSL
czw., 3 sty 2019 o 17:52 Olivier Houchard napisał(a): > Ah I think I figured it out. > OpenSSL added anti-replay protection when using early data, and it messes up > with the session handling. > With the updated attached patch, I get early data to work again. Is it better > for you ? Now it works. However, I am a bit concerned about disabling something that sounds like an important safeguard. Reading this https://www.openssl.org/docs/man1.1.1/man3/SSL_SESSION_get_max_early_data.html#REPLAY-PROTECTION suggests that it is really not a wise thing to do. And again, s_server works differently. It does not use SSL_OP_NO_ANTI_REPLAY but the resumption, with early data, works, once. Then you get new session that you can resume again if you wish, but also once. You cannot resume the same session twice. With your patch I can resume single session as many times as I wish. Coupled with early data this is exactly something that TLS 1.3 RFC warns against. This probably is due to haproxy using external session management. I'll try to dig more into this on weekend, now that I know where to look. -- Janusz Dziemidowicz
Re: State of 0-RTT TLS resumption with OpenSSL
Hi Janusz, On Thu, Jan 03, 2019 at 11:49:35AM +0100, Janusz Dziemidowicz wrote: > ??r., 2 sty 2019 o 19:04 Olivier Houchard napisa??(a): > > You're right indeed. 0RTT was added with a development version of OpenSSL > > 1.1.1, > > which had a default value for max early data of 16384, but it was changed to > > 0 in the meanwhile. > > Does the attached patch work for you ? > > This indeed results in following when using s_client: > Max Early Data: 16385 > > However, I believe it still does not work. I was trying again to test > it with s_client. > > Without allow-0rtt option I can resume TLS 1.3 session without problem: > openssl s_client -connect host:port -sess_out sessfile > openssl s_client -connect host:port -sess_in sessfile > This results with: > Reused, TLSv1.3, Cipher is TLS_CHACHA20_POLY1305_SHA256 > > As soon as I add allow-0rtt (and your patch) above s_client results > always with a new session: > New, TLSv1.3, Cipher is TLS_CHACHA20_POLY1305_SHA256 > No matter what I do I was not able to resume any session with allow-0rtt > active. > > Just to rule out that I am using s_client in a wrong way I've made the > same test against s_server. I was able to successfully resume session > and even send early data that was accepted. So I believe that there is > still something wrong in haproxy with TLS session handling. > Ah I think I figured it out. OpenSSL added anti-replay protection when using early data, and it messes up with the session handling. With the updated attached patch, I get early data to work again. Is it better for you ? Regards, Olivier >From 82126322107bc628e32ff300195951fd660a43ac Mon Sep 17 00:00:00 2001 From: Olivier Houchard Date: Wed, 2 Jan 2019 18:46:41 +0100 Subject: [PATCH] BUG/MEDIUM: ssl: Disable anti-replay protection and set max data with 0RTT. When using early data, disable the OpenSSL anti-replay protection, and set the max amount of early data we're ready to accept, based on the size of buffers, or early data won't work with the released OpenSSL 1.1.1. This should be backported to 1.8. --- src/ssl_sock.c | 4 1 file changed, 4 insertions(+) diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 282b85dd..13ce2e5b 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -3869,6 +3869,10 @@ ssl_sock_initial_ctx(struct bind_conf *bind_conf) SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk); SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk); #elif (OPENSSL_VERSION_NUMBER >= 0x10101000L) + if (bind_conf->ssl_conf.early_data) { + SSL_CTX_set_options(ctx, SSL_OP_NO_ANTI_REPLAY); + SSL_CTX_set_max_early_data(ctx, global.tune.bufsize - global.tune.maxrewrite); + } SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL); SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk); #else -- 2.14.4
Re: State of 0-RTT TLS resumption with OpenSSL
śr., 2 sty 2019 o 19:04 Olivier Houchard napisał(a): > You're right indeed. 0RTT was added with a development version of OpenSSL > 1.1.1, > which had a default value for max early data of 16384, but it was changed to > 0 in the meanwhile. > Does the attached patch work for you ? This indeed results in following when using s_client: Max Early Data: 16385 However, I believe it still does not work. I was trying again to test it with s_client. Without allow-0rtt option I can resume TLS 1.3 session without problem: openssl s_client -connect host:port -sess_out sessfile openssl s_client -connect host:port -sess_in sessfile This results with: Reused, TLSv1.3, Cipher is TLS_CHACHA20_POLY1305_SHA256 As soon as I add allow-0rtt (and your patch) above s_client results always with a new session: New, TLSv1.3, Cipher is TLS_CHACHA20_POLY1305_SHA256 No matter what I do I was not able to resume any session with allow-0rtt active. Just to rule out that I am using s_client in a wrong way I've made the same test against s_server. I was able to successfully resume session and even send early data that was accepted. So I believe that there is still something wrong in haproxy with TLS session handling. -- Janusz Dziemidowicz
Re: State of 0-RTT TLS resumption with OpenSSL
Hi Janusz, On Sun, Dec 30, 2018 at 05:38:26PM +0100, Janusz Dziemidowicz wrote: > Hi, > I've been trying to get 0-RTT resumption working with haproxy 1.8.16 > and OpenSSL 1.1.1a. > No matter what I put in configuration file, testing with openssl > s_client always results in: > Max Early Data: 0 > > OK, let's look at ssl_sock.c > The only thing that seems to try to enable 0-RTT is this: > #ifdef OPENSSL_IS_BORINGSSL > if (allow_early) > SSL_set_early_data_enabled(ssl, 1); > #else > if (!allow_early) > SSL_set_max_early_data(ssl, 0); > #endif > > But I fail to see how this is supposed to work. OpenSSL has 0-RTT > disabled by default. To enable this one must call > SSL_set_max_early_data with the amount of bytes it is willing to read. > The above simply does... nothing. > > Is it supposed to work at all or do I miss something? ;) > You're right indeed. 0RTT was added with a development version of OpenSSL 1.1.1, which had a default value for max early data of 16384, but it was changed to 0 in the meanwhile. Does the attached patch work for you ? Thanks ! Olivier >From cdb864da7cebb97800aef2e114bae6f0d0f96814 Mon Sep 17 00:00:00 2001 From: Olivier Houchard Date: Wed, 2 Jan 2019 18:46:41 +0100 Subject: [PATCH] MEDIUM: ssl: Call SSL_CTX_set_max_early_data() to enable 0RTT. When we want to enable early data on a listener, explicitely call SSL_CTX_set_max_early_data(), as the default is now 0. This should be backported to 1.8. --- src/ssl_sock.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 282b85dd..c24de955 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -3869,6 +3869,8 @@ ssl_sock_initial_ctx(struct bind_conf *bind_conf) SSL_CTX_set_select_certificate_cb(ctx, ssl_sock_switchctx_cbk); SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk); #elif (OPENSSL_VERSION_NUMBER >= 0x10101000L) + if (bind_conf->ssl_conf.early_data) + SSL_CTX_set_max_early_data(ctx, global.tune.bufsize - global.tune.maxrewrite); SSL_CTX_set_client_hello_cb(ctx, ssl_sock_switchctx_cbk, NULL); SSL_CTX_set_tlsext_servername_callback(ctx, ssl_sock_switchctx_err_cbk); #else -- 2.14.4