Re: State of 0-RTT TLS resumption with OpenSSL

2019-01-09 Thread Willy Tarreau
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

2019-01-09 Thread Olivier Houchard
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

2019-01-08 Thread Willy Tarreau
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

2019-01-08 Thread Olivier Houchard
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

2019-01-08 Thread Janusz Dziemidowicz
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

2019-01-04 Thread Olivier Houchard
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

2019-01-04 Thread Janusz Dziemidowicz
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

2019-01-03 Thread Olivier Houchard
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

2019-01-03 Thread Janusz Dziemidowicz
ś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

2019-01-02 Thread Olivier Houchard
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



State of 0-RTT TLS resumption with OpenSSL

2018-12-30 Thread Janusz Dziemidowicz
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? ;)

-- 
Janusz Dziemidowicz