Subject: Re: [TLS] Commentary on the client authentication presentation slides

From: Ilari Liusvaara <[email-masked]>
Date: Sat, 1 Aug 2015 11:48:49 +0300

> On Tue, Jul 28, 2015 at 6:28 PM David Benjamin <[email-masked]> wrote:
> 
> > Are you intending that this mechanism be enabled by default for HTTP/2 or
> > would the prohibition against renego still apply? Without any way for the
> > client to tie the CertificateRequest to the HTTP request that triggered it,
> > this mechanism would have many of the same problems as renego as far as
> > HTTP/2 is concerned. (I realize Microsoft has a draft floating around for a
> > TLS_RENEG_PERMITTED HTTP/2 setting. The setting can control this too I
> > suppose.)

Even if there would be way to tie it to request that triggered the request,
it would still IMO have some of the nastiest problems of renegotiation,
especially in context of HTTP/2 in web (the privilege involved is almost
impossible to handle in any sane way).

What I think would be very useful: A way for client to signal it has a
client certificate it expects to use, regardless of if valid configuration
is known. The vast majority of times client certificate is used, the
client knows about that before initiating a connection.

IMO, the proper way to handle "this resource requires client certificate"
is for server to signal that in application protocol and then client to
establish a new connection with client certificate (or if application
protocol supports it, do the authentication at application layer without
ever involving TLS, except for channel binding).

-Ilari

---

From: David Benjamin <[email-masked]>
Date: Sun, 02 Aug 2015 15:38:00 +0000

> client knows about that before initiating a connection.

Unless I misunderstand you, this isn't true for a browser. Browsers only
look for client certificates based on a CertificateRequest message. Some
platforms, like Android, don't even let you list the user's certificate
store. Instead there's an API to show a trusted certificate picker prompt.

Or, given the paragraph below, are you suggesting that we'd start a second
connection on receiving CertificateRequest and only advertise it then?
Yeah, that's actually how Chrome implements client auth anyway. We always
start a second connection with a client certificate configured, even if the
server sent CertificateRequest on a renego. It makes a few things simpler.

> ever involving TLS, except for channel binding).

Certainly. Chrome doesn't implement TLS_RENEG_PERMITTED for HTTP/2, and I
don't want to allow this mechanism for it either. I consider renego-based
per-resource client auth in HTTP/1.1 to be a legacy mistake we're currently
stuck with. (It's the only reason we ever have to renego. In BoringSSL,
we've settled on stripping renego down to the bare minimum needed to
support this. Simplifies a lot of stuff.)

I'm guessing Microsoft has different constraints/goals, given this proposal
and TLS_RENEG_PERMITTED, so if we must have it in the transport, I'd rather
it be some opt-in corner that I don't have to deal with. (Applications can
return HTTP_1_1_REQUIRED in HTTP/2 if they really must do per-resource
client auth.) But I do agree this is a problematic mechanism and don't
think it belongs in TLS. Let the application layer do it with a channel
binding. No need for new connections, and no messy questions about scope
and multi-request protocols.

David

---

From: Ilari Liusvaara <[email-masked]>
Date: Sun, 2 Aug 2015 21:29:08 +0300

> store. Instead there's an API to show a trusted certificate picker prompt.

Well, TLS is also used for non-browser HTTPS and stuff other than HTTPS.
There one likely "preconfigures" client certificates if needed.

> server sent CertificateRequest on a renego. It makes a few things simpler.

Doesn't that count as "knowing about client certificate before connecting"
(even if the knowledge has been received split-second before TLS handshake
starts)?

Also, signaling can be at application layer, as talked about below.

> support this. Simplifies a lot of stuff.)

Yeah, I consider it (renego auth in HTTP/1.1) a poor idea as well, and I
consider it would be actively dangerous in browser HTTP/2 (due to the
multipoint nature of the environment and multiplexed nature of HTTP/2)...
Good thing it is banned.

> and multi-request protocols.

Summary of what auth modes I think are needed:

- TLS-level client certificate auth on client request on connect (this
  currently can't be cleanly done, sometimes one even sees that "renego
  immediately to provoke CR" hack).
- Application-level client auth (via CB capability of TLS).

-Ilari

---

From: Andrei Popov <[email-masked]>
Date: Tue, 4 Aug 2015 00:37:47 +0000

> There one likely "preconfigures" client certificates if needed.
The proposed client authentication mechanism specifically addresses the case where the client does not have one "preconfigured" cert.

>  immediately to provoke CR" hack).
With the proposed change, there will be no need to renegotiate in order to authenticate the client.

 > - Application-level client auth (via CB capability of TLS).
The proposed mechanism does not preclude this option.

Cheers,

Andrei

-----Original Message-----
From: Ilari Liusvaara [mailto:[email-masked]] 
Sent: Sunday, August 2, 2015 11:29 AM
To: David Benjamin <[email-masked]>
Cc: Andrei Popov <[email-masked]>; [email-masked]
Subject: Re: [TLS] Commentary on the client authentication presentation slides

On Sun, Aug 02, 2015 at 03:38:00PM +0000, David Benjamin wrote:
> > What I think would be very useful: A way for client to signal it has 
> > a client certificate it expects to use, regardless of if valid 
> > configuration is known. The vast majority of times client 
> > certificate is used, the client knows about that before initiating a connection.
> 
> Unless I misunderstand you, this isn't true for a browser. Browsers 
> only look for client certificates based on a CertificateRequest 
> message. Some platforms, like Android, don't even let you list the 
> user's certificate store. Instead there's an API to show a trusted certificate picker prompt.

> Or, given the paragraph below, are you suggesting that we'd start a 
> second connection on receiving CertificateRequest and only advertise it then?
> Yeah, that's actually how Chrome implements client auth anyway. We 
> always start a second connection with a client certificate configured, 
> even if the server sent CertificateRequest on a renego. It makes a few things simpler.

Doesn't that count as "knowing about client certificate before connecting"
(even if the knowledge has been received split-second before TLS handshake starts)?

> > is for server to signal that in application protocol and then client 
> > to establish a new connection with client certificate (or if 
> > application protocol supports it, do the authentication at 
> > application layer without ever involving TLS, except for channel binding).
> 
> Certainly. Chrome doesn't implement TLS_RENEG_PERMITTED for HTTP/2, 
> and I don't want to allow this mechanism for it either. I consider 
> renego-based per-resource client auth in HTTP/1.1 to be a legacy 
> mistake we're currently stuck with. (It's the only reason we ever have 
> to renego. In BoringSSL, we've settled on stripping renego down to the 
> bare minimum needed to support this. Simplifies a lot of stuff.)

Yeah, I consider it (renego auth in HTTP/1.1) a poor idea as well, and I consider it would be actively dangerous in browser HTTP/2 (due to the multipoint nature of the environment and multiplexed nature of HTTP/2)...
Good thing it is banned.

> I'm guessing Microsoft has different constraints/goals, given this 
> proposal and TLS_RENEG_PERMITTED, so if we must have it in the 
> transport, I'd rather it be some opt-in corner that I don't have to 
> deal with. (Applications can return HTTP_1_1_REQUIRED in HTTP/2 if 
> they really must do per-resource client auth.) But I do agree this is 
> a problematic mechanism and don't think it belongs in TLS. Let the 
> application layer do it with a channel binding. No need for new 
> connections, and no messy questions about scope and multi-request protocols.

-Ilari

---

From: Ilari Liusvaara <[email-masked]>
Date: Sat, 8 Aug 2015 12:03:51 +0300

On Tue, Aug 04, 2015 at 12:37:47AM +0000, Andrei Popov wrote:
> The proposed client authentication mechanism specifically addresses
> the case where the client does not have one "preconfigured" cert.

What sort of usecase you have in mind for this? I can't come up with
single one that I don't think is a hack at best.

Note: It is very easy to misuse capability like this (even if it is
restricted to work only once per connection) to create nasty security
issues (one example being trying to use this for HTTP/2 in browser
environment).

> order to authenticate the client.

Where's the capability for client to unilaterially decide to send a
certificate without valid configuration? The 0-RTT certificate
authentication requires a valid configuration.

E.g. one way to implement that would be certificate_request_request
extension, which would request server to send a CertificateRequest.

Tho with the changes to always sign the key exchange, using 0-RTT
client certs doesn't work unless the server requested certificates
back then.

> The proposed mechanism does not preclude this option.

That was given as second of two entries in list of kinds of
authentication I think are useful (and precluding it would mean
removing TLS-Unique and TLS-Extractor, which is something that I really
don't see happening).

-Ilari

---

From: Andrei Popov <[email-masked]>
Date: Mon, 10 Aug 2015 17:10:38 +0000

Hi Ilari,

> What sort of usecase you have in mind for this?
This is to support a fairly common website design where the landing page does not require client auth, but subsequent request to a protected resource triggers client authentication within an existing TLS connection.
In TLS<=1.2, this was accomplished via renegotiation. In TLS1.3, there is no renegotiation, so we need an alternative solution if we want to support these existing sites over TLS1.3.

> Where's the capability for client to unilaterially decide to send a certificate without valid configuration?
My pull request is designed to address client auth in the middle of a TLS connection, after the handshake is complete, which is an existing scenario that was broken by the removal of renegotiation in TLS 1.3.
If enough people want the capability for the client to volunteer a certificate, I don't mind adding this to my pull request. Right now I don't have a sense of how useful WG participants think this would be.

Cheers,

Andrei

-----Original Message-----
From: Ilari Liusvaara [mailto:[email-masked]] 
Sent: Saturday, August 8, 2015 2:04 AM
To: Andrei Popov <[email-masked]>
Cc: David Benjamin <[email-masked]>; [email-masked]
Subject: Re: [TLS] Commentary on the client authentication presentation slides

> the case where the client does not have one "preconfigured" cert.

What sort of usecase you have in mind for this? I can't come up with single one that I don't think is a hack at best.

Note: It is very easy to misuse capability like this (even if it is restricted to work only once per connection) to create nasty security issues (one example being trying to use this for HTTP/2 in browser environment).

> > - TLS-level client certificate auth on client request on connect 
> > (this  currently can't be cleanly done, sometimes one even sees that 
> > "renego  immediately to provoke CR" hack).

Where's the capability for client to unilaterially decide to send a certificate without valid configuration? The 0-RTT certificate authentication requires a valid configuration.

E.g. one way to implement that would be certificate_request_request extension, which would request server to send a CertificateRequest.

Tho with the changes to always sign the key exchange, using 0-RTT client certs doesn't work unless the server requested certificates back then.

> The proposed mechanism does not preclude this option.

That was given as second of two entries in list of kinds of authentication I think are useful (and precluding it would mean removing TLS-Unique and TLS-Extractor, which is something that I really don't see happening).

-Ilari

---

From: Yoav Nir <[email-masked]>
Date: Mon, 10 Aug 2015 20:28:14 +0300

> On Aug 10, 2015, at 8:10 PM, Andrei Popov <[email-masked]> wrote:
> 
> Hi Ilari,
> 

I’d like to point out that I am very interested in this use case, but I’m not sure that this is the solution.

Such sites were first broken by HTTP/2 which forbade renegotiation. Then they were broken again by TLS 1.3 that does not include renegotiation.

Ideally a solution would work with HTTP/1 over TLS 1.3, HTTP/2 over TLS 1.3, HTTP/2 over TLS 1.2, and for completeness HTTP/1 over TLS 1.2. 

Assuming that HTTP/2 is the HTTP of the future (meaning that relegating these sites to HTTP/1 is a temporary thing), I don’t think that this new mechanism fixes the issue with renegotiation that caused httpbis to reject its usage. We still get a race condition where several requests might be answered before, after or during authentication depending on the timing of the TLS handshake message vs the HTTP messages.

It would be useless IMO to create an alternate renegotiation in TLS only for it to not be used in HTTP/2.

Yoav

---

From: Andrei Popov <[email-masked]>
Date: Mon, 10 Aug 2015 19:04:57 +0000

> Ideally a solution would work with HTTP/1 over TLS 1.3, HTTP/2 over TLS 1.3, HTTP/2 over TLS 1.2, and for completeness HTTP/1 over TLS 1.2.
Correct, anything less than this will create deployment problems.

> I’d like to point out that I am very interested in this use case, but I’m not sure that this is the solution.
I'm open to alternatives that fix the broken use case. 

> We still get a race condition where several requests might be answered before, after or during authentication depending on the timing of the TLS handshake message vs the HTTP messages.
The idea is that before answering a request that requires client auth, the server checks if a client cred is available. If there is no suitable client cred available, the request is blocked until the client authenticates. This does not necessarily have to block other requests that do not require client auth.

Cheers,

Andrei

-----Original Message-----
From: Yoav Nir [mailto:[email-masked]] 
Sent: Monday, August 10, 2015 10:28 AM
To: Andrei Popov <[email-masked]>
Cc: Ilari Liusvaara <[email-masked]>; [email-masked]
Subject: Re: [TLS] Commentary on the client authentication presentation slides

Yoav

---

From: David Benjamin <[email-masked]>
Date: Mon, 10 Aug 2015 19:33:53 +0000

On Mon, Aug 10, 2015 at 3:05 PM Andrei Popov <[email-masked]>
wrote:

> > Ideally a solution would work with HTTP/1 over TLS 1.3, HTTP/2 over TLS
> 1.3, HTTP/2 over TLS 1.2, and for completeness HTTP/1 over TLS 1.2.

But this proposal is only suitable for HTTP/1 over TLS 1.3 anyway. It can't
be used for HTTP/2 over TLS 1.3 as a client has no way to correlate
transport-level certificate requests with the HTTP request. This is part of
why renego was rightly banned for HTTP/2. Otherwise you need to show a
contextless prompt on a client, and that's really bad UI. Chrome tries very
hard to avoid those.

I would grudgingly consider it acceptable for HTTP/1 over TLS 1.3, but only
because it's no worse than the renego one and we're stuck with that legacy
mistake right now. If that weren't the case, I wouldn't want it in HTTP/1
either. Changing connection-level state mid-stream underneath a
multi-request protocol is very messy, particularly when combined with
socket-pooling optimizations.

Why not do this using HTTP's own auth framework? Have the client sign
something which includes a channel binding, placing it and the certificate
chain in an Authorization header. You could even transition to it in TLS
1.2 deployments, provided EMS is negotiated. When TLS 1.3 and EMS are not
negotiated, fall back to the legacy thing.

David

> > We still get a race condition where several requests might be answered
> before, after or during authentication depending on the timing of the TLS
> handshake message vs the HTTP messages.
> The idea is that before answering a request that requires client auth, the
> server checks if a client cred is available. If there is no suitable client
> cred available, the request is blocked until the client authenticates. This
> does not necessarily have to block other requests that do not require
> client auth.
>
> Cheers,
>
> Andrei
>
> > This is to support a fairly common website design where the landing page
> does not require client auth, but subsequent request to a protected
> resource triggers client authentication within an existing TLS connection.
> > In TLS<=1.2, this was accomplished via renegotiation. In TLS1.3, there
> is no renegotiation, so we need an alternative solution if we want to
> support these existing sites over TLS1.3.
>
> Such sites were first broken by HTTP/2 which forbade renegotiation. Then
> they were broken again by TLS 1.3 that does not include renegotiation.
>
> Ideally a solution would work with HTTP/1 over TLS 1.3, HTTP/2 over TLS
> 1.3, HTTP/2 over TLS 1.2, and for completeness HTTP/1 over TLS 1.2.
>
> Assuming that HTTP/2 is the HTTP of the future (meaning that relegating
> these sites to HTTP/1 is a temporary thing), I don’t think that this new
> mechanism fixes the issue with renegotiation that caused httpbis to reject
> its usage. We still get a race condition where several requests might be
> answered before, after or during authentication depending on the timing of
> the TLS handshake message vs the HTTP messages.
>
> _______________________________________________
> TLS mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/tls
>

---

From: Yoav Nir <[email-masked]>
Date: Mon, 10 Aug 2015 22:53:22 +0300

> On Aug 10, 2015, at 10:04 PM, Andrei Popov <[email-masked]> wrote:
> 

One solution would be to move the authentication for this use case (and perhaps for HTTPS in general) from the transport layer to either HTTP as an authentication method or to the application (through some standardized exchange of JSON objects).

Another option is to allow renegotiation and your mechanism in HTTP/2 with some change of behavior that eliminates the race condition. For example:
 1. The server receives a request for a resource that requires a client certificate
 2. The server sends a new HTTP message (or code) that says that client certificate authentication is required.
 3. The client sends a new HTTP control frame with the highest number of resource that it has requested.
 4. The server finishes serving all resources that don’t need authentication with a number below what the client sent
 5. The client does not initiate any new requests.
 6. When the server is done, it initiates renegotiation or the new mechanism
 7. After renegotiation, the client can resume sending requests, all of which are authenticated.

The details may be different, but something like this can bring determinism to the process.

> The idea is that before answering a request that requires client auth, the server checks if a client cred is available. If there is no suitable client cred available, the request is blocked until t…

This is a somewhat contrived example, but consider an object in the web page that says “Hello, guest” when no credential is available, and “Hello, Andrei” when a credential is available.  If the page has optional authentication and you have presented the certificate, then depending on timing you might still see “Hello, guest” on the page.

Yoav

---

From: Andrei Popov <[email-masked]>
Date: Mon, 10 Aug 2015 20:18:05 +0000

> One solution would be to move the authentication for this use case (and perhaps for HTTPS in general) from the transport layer to either HTTP as an authentication method or to the application (thro…
Doesn't this require an update of the site? If so, it defeats our goal of supporting existing sites over new protocols.

> Another option is to allow renegotiation and your mechanism in HTTP/2 with some change of behavior that eliminates the race condition.
I'm not sure what purpose #3 (HTTP control frame with the highest number of resource) serves. Couldn't we just say the client must not send new requests after receiving CertificateRequest and until sending CertificateVerify?

> This is a somewhat contrived example, but consider an object in the web page that says “Hello, guest” when no credential is available, and “Hello, Andrei” when a credential is available.  If the pa…
This just means that a request was answered at the time there was no client credential. This page probably needs to be a resource that requires client auth.

-----Original Message-----
From: Yoav Nir [mailto:[email-masked]] 
Sent: Monday, August 10, 2015 12:53 PM
To: Andrei Popov <[email-masked]>
Cc: Ilari Liusvaara <[email-masked]>; [email-masked]
Subject: Re: [TLS] Commentary on the client authentication presentation slides

Another option is to allow renegotiation and your mechanism in HTTP/2 with some change of behavior that eliminates the race condition. For example:
 1. The server receives a request for a resource that requires a client certificate  2. The server sends a new HTTP message (or code) that says that client certificate authentication is required.
 3. The client sends a new HTTP control frame with the highest number of resource that it has requested.
 4. The server finishes serving all resources that don’t need authentication with a number below what the client sent  5. The client does not initiate any new requests.
 6. When the server is done, it initiates renegotiation or the new mechanism  7. After renegotiation, the client can resume sending requests, all of which are authenticated.

Yoav

---

From: Ilari Liusvaara <[email-masked]>
Date: Tue, 11 Aug 2015 08:00:40 +0300

> negotiated, fall back to the legacy thing.

Yeah, that would be much cleaner (and indeed was one[1] of the two ways
I think HTTP/2 client auth can be done without gross hacks).

Except that because for clean operation HTTP needs request-level
authentication, one would have to transmit the authentication
on each request (fortunately, on subsequent retransmits, it
can be compressed very well[2]).

[1] The other would be signaling via HTTP 401 and using that to
trigger new connection with client-driven client auth.

[2] Unless the payload needs internal nonces (and I don't think
it does), one can assume the same certificate on the same connection
always generates the same cert+signature block (if using deterministic
signatures, that happens even if one tries to sign again).

-Ilari

---

From: Dave Garrett <[email-masked]>
Date: Tue, 11 Aug 2015 02:05:58 -0400

> In TLS<=1.2, this was accomplished via renegotiation. In TLS1.3, there is no renegotiation, so we need an alternative solution if we want to support these existing sites over TLS1.3.

This is just an idea, but what about just allowing a renegotiation-like mechanism via 0-RTT with PSK resumption to be triggered on a TLS alert or HTTP response code? The rough idea would be like this:

1) client connects to server and fetches public resources
2) client requests restricted resource; server sends auth required response (TLS alert or HTTP code)
3) client creates a replacement connection using PSK-based resumption and early data in the first flight for the request along with the client cert.

There's a 1 roundtrip cost in there for a new TCP connection, which could possibly be optimized away by using TCP fast open.

This general concept is relatively simple in comparison to doing something mid-connection. Instead of attempting to renegotiate on an existing connection, just make creation of resumed connections cheap enough to start over with client auth in the handshake from the start.

It's a very rough idea, but I'm wondering if it sounds like something worth discussing.

Dave

---

From: Martin Thomson <[email-masked]>
Date: Tue, 11 Aug 2015 09:39:19 -0700

Before people get too far down that road, here:

https://tools.ietf.org/html/draft-thomson-httpbis-cant-01
https://tools.ietf.org/html/draft-thomson-tls-care-00

Andrei has made it clear that these do not work for his use case (I'm
not yet convinced that they are inadequate, but I am convinced of the
fact that Andrei thinks that they are inadequate ;).

Also:

https://tools.ietf.org/html/draft-ietf-httpbis-http2-00#section-2.6.9

This is well-trodden ground.

---

From: Andrei Popov <[email-masked]>
Date: Tue, 11 Aug 2015 18:10:53 +0000

Indeed, I think cant-care has a number of disadvantages:
1. Introduces round-trips to establish a new TCP connection;
2. Requires a new TLS handshake, with associated costs.
3. Uses two CertificateRequests: one at the HTTP layer, and another at the TLS layer. Somehow we would need to figure out how to make them match, or have the client ignore TLS-level cert filtering parameters?
4. Pushes the problem to the application layer: any application protocol that uses mid-stream client auth will require an update. (I know, some will say we are only aware of HTTPS scenarios right now.)

At the cost of all of the above, cant-care allows the client to determine exactly which HTTP request has resulted in the client auth request. I think there may be a compromise where we can identify this HTTP request without requiring a reconnect. E.g. what about CertificateRequest at the HTTP layer + TLS client sending Certificate/CertificateVerify after the handshake in the middle of the existing TLS connection?

Cheers,

Andrei

-----Original Message-----
From: TLS [mailto:[email-masked]] On Behalf Of Martin Thomson
Sent: Tuesday, August 11, 2015 9:39 AM
To: Dave Garrett <[email-masked]>
Cc: [email-masked]
Subject: Re: [TLS] Commentary on the client authentication presentation slides

Andrei has made it clear that these do not work for his use case (I'm not yet convinced that they are inadequate, but I am convinced of the fact that Andrei thinks that they are inadequate ;).

Also:

---

From: [email-masked] (Martin Rex)
Date: Wed, 19 Aug 2015 17:56:54 +0200 (CEST)

Andrei Popov wrote:
> This is to support a fairly common website design where the landing
> page does not require client auth, but subsequent request to a
> protected resource triggers client authentication within an existing
> TLS connection.
>
> In TLS<=1.2, this was accomplished via renegotiation. In TLS1.3,
> there is no renegotiation, so we need an alternative solution if we
> want to support these existing sites over TLS1.3.

While this might have been the structure of a few legacy sites,
this will meet the axe longe before TLSv1.3 is done, because
HTTP/2 prohibits renegotiation with TLSv1.2 as well.

R.I.P. renegotiation.

-Martin