Subject: [Unbearable] (late, sorry) WGLC question on establishing the binding or not

From: Brian Campbell <[email-masked]>
Date: Mon, 19 Dec 2016 16:29:28 -0700

What should a server do if it receives an HTTP request without a
Sec-Token-Binding header on a TLS connection where token binding was
negotiated in the handshake?

As far as I can tell from my reading, the drafts don't explicitly say (TBPROTO
4.2 <https://tools.ietf.org/html/draft-ietf-tokbind-protocol-11#section-4.2>
doesn't cover it, for example). I'm guessing that it is to allow for how TB
version negotiation is intended to work - i.e. client sends version 1.1 in
the TB extension, server responds with version 1.0, but the client only
supports 1.1 so the binding isn't established and no TokenBindingMessage is
sent.

I can't wrap my head around what exactly, if anything, is wrong with all
that but it's always felt a little off to me. Nick sort of mentioned it on
the list back in August
<https://www.ietf.org/mail-archive/web/unbearable/current/msg00675.html>but
it was kinda lost as part of a larger conversation about the versioning.

Should the server behavior in that situation be more explicitly covered in
the spec(s)? I'm thinking maybe so. The case where the client and server
both indicate exactly the same versions during negotiation but no
TokenBindingMessage is sent, for example, seems like it should be a failure
condition in the same vein as a mismatch between the negotiated
TokenBindingKeyParameters and in the the TokenBindingKeyParameters of the
provided_token_binding TokenBindingID.

Please correct me, if I'm off the rails here. But explain why. And I do
think that my uncertainty/confusion does suggest that some kind of
clarification in the draft(s) would be useful.

Thanks,
Brian

---

From: Andrei Popov <[email-masked]>
Date: Tue, 20 Dec 2016 00:37:16 +0000

Ø  What should a server do if it receives an HTTP request without a Sec-Token-Binding header on a TLS connection where token binding was negotiated in the handshake?
This means TB is not established with this client, see TBNEGO: “If the client does not support the Token Binding protocol version selected by the server, then the connection proceeds without Token Binding.”

Ø  The case where the client and server both indicate exactly the same versions during negotiation but no TokenBindingMessage is sent, for example, seems like it should be a failure condition in the same vein as a mismatch between the negotiated TokenBindingKeyParameters and in the the TokenBindingKeyParameters of the  provided_token_binding TokenBindingID.

We could special-case and say that if a server picks the exact TB version a client sent, and the client’s subsequent request does not contain the TB message, then the request MUST be rejected.
However, in practice this feels like a failure case for no good reason.

I think we have 4 possibilities:

1.       The client sends a TB message and a bound token => the server verifies per TBPROTO.

2.       The client sends a TB message and no bound token => the server verifies per TBPROTO.

3.       The client sends no TB message and a bound token => the server rejects per TBPROTO.

4.       The client sends no TB message and no bound token => we could require that this be rejected, if the server picked the client’s offered TB version, but why create this failure case?

Cheers,

Andrei

---

From: Brian Campbell <[email-masked]>
Date: Tue, 20 Dec 2016 12:53:59 -0700

Thanks Andrei, some further discussion inline...

On Mon, Dec 19, 2016 at 5:37 PM, Andrei Popov <[email-masked]>
wrote:

> Ø  What should a server do if it receives an HTTP request without a
> This means TB is not established with this client, see TBNEGO: “If the
> client does not support the Token Binding protocol version selected by the
> server, then the connection proceeds without Token Binding.”
>
I knew I'd seen something like that somewhere but couldn't conjure it up.
Thanks for the pointer/reminder.

But in defense of my own dumb question, that clearly covers the case where
the client doesn't support the TB version that the server chose. But
doesn't address the case where the client and server both indicate exactly
the same versions during negotiation but no TB message is sent at the
application layer.

Ø  The case where the client and server both indicate exactly the same
> versions during negotiation but no TokenBindingMessage is sent, for
> example, seems like it should be a failure condition in the same vein as a
> mismatch between the negotiated TokenBindingKeyParameters and in the the
> TokenBindingKeyParameters of the  provided_token_binding TokenBindingID.
>
>
>
> We could special-case and say that if a server picks the exact TB version
> a client sent, and the client’s subsequent request does not contain the TB
> message, then the request MUST be rejected.
>
> 4.       The client sends no TB message and no bound token => we could
> require that this be rejected, if the server picked the client’s offered TB
> version, but why create this failure case?
>
I'm not sure to be honest. That's why I'm asking. I don't fully understand
the reasoning behind the requirements that exist between the handshake
negotiation to checking the TB message. And the treatment of this case
feels a bit inconsistent to me. If TB was not negotiated but a TB message
is sent, reject the bindings. If TB was negotiated but the keyparams of the
provided TB in the TB message doesn't match the negotiated keyparams,
reject the bindings. When the TB version negotiated is identical but a TB
message isn't sent, it would seem to suggest at least a misbehaving client.
Maybe that's okay though. Even as I write it, it doesn't seem as
inconsistent as it did in my mind before. But I'm asking to try and better
understand the ramifications of the case. And the others. Are there
implications beyond a misbehaving client in the case of a mismatch between
the key parameters type that was negotiated and the key parameters type of
the provided_token_binding in the TB message?

---

From: Nick Harper <[email-masked]>
Date: Tue, 20 Dec 2016 12:04:19 -0800

On Tue, Dec 20, 2016 at 11:53 AM, Brian Campbell <[email-masked]

> Since in this case (client and server sent exact same TB version in nego)
a server knows that the client supports TB, so if the client doesn't send a
TB message, either some sort of weird attack is happening (which we
definitely don't want), or the client is buggy and negotiated TB when it
shouldn't have. I would suggest that when servers can detect buggy clients,
they be as strict as possible, which would mean TB should say that a server
SHOULD reject the TB message (and maybe close the connection) in this case.

>
>
>
>
>
> _______________________________________________
> Unbearable mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/unbearable
>
>

---

From: Andrei Popov <[email-masked]>
Date: Tue, 20 Dec 2016 20:11:34 +0000

Ø  I don't fully understand the reasoning behind the requirements that exist between the handshake negotiation to checking the TB message.
I’ll try to help with this.

Ø  If TB was not negotiated but a TB message is sent, reject the bindings.
The server that isn’t configured to use TB should not incur TB verification costs.

Ø  If TB was negotiated but the keyparams of the provided TB in the TB message doesn't match the negotiated keyparams, reject the bindings.
Right, so there is no downgrade from what’s negotiated. Also, this prevents the client using parameters unsupported by the server.

Ø  When the TB version negotiated is identical but a TB message isn't sent, it would seem to suggest at least a misbehaving client.
Yes, but if there’s no bound token in the request, I think the server can ignore the lack of TB message (please let me know if you have an attack in mind).
If this request has a bound token in it, existing language will require the server to reject.

Cheers,

Andrei

---

From: Nick Harper <[email-masked]>
Date: Tue, 20 Dec 2016 12:57:53 -0800

On Tue, Dec 20, 2016 at 12:11 PM, Andrei Popov <[email-masked]>
wrote:
>
> Ø  When the TB version negotiated is identical but a TB message isn't
> sent, it would seem to suggest at least a misbehaving client.
>
> Yes, but if there’s no bound token in the request, I think the server can
> ignore the lack of TB message (please let me know if you have an attack in
> mind).
>

I don't have a specific attack in mind here (perhaps you could have a mitm
that's negotiating TB but then stripping TB messages, but that seems like a
worse attack than the mitm not negotiating TB at all). I made an assumption
that a client that negotiates TB but then doesn't send a TB message in
accordance with the application profile is buggy. If this is a bug, I think
servers should fail to inter-operate with it to reduce the number of buggy
TB implementations in the ecosystem.

---

From: Brian Campbell <[email-masked]>
Date: Tue, 20 Dec 2016 15:01:40 -0700

> SHOULD reject the TB message (and maybe close the connection) in this case.

There's no TB message in that case so it'd have to be reject the
application message (I guess a 400 for HTTP). But that's basically the same
train of thought that I had. I don't feel all that strongly about it but
that does align with my thoughts.

---

From: Brian Campbell <[email-masked]>
Date: Tue, 20 Dec 2016 15:23:37 -0700

On Tue, Dec 20, 2016 at 1:11 PM, Andrei Popov <[email-masked]>
wrote:

> Ø  I don't fully understand the reasoning behind the requirements that
> exist between the handshake negotiation to checking the TB message.
>

Thanks.

> The server that isn’t configured to use TB should not incur TB

I'd assume a server that doesn't support TB will ignore TB messages because
it doesn't know about TB. That bit is from Server Processing Rules in
TBPROTO so I read it as a requirement of the server on how to react to a
misbehaving client.

> Ø  If TB was negotiated but the keyparams of the provided TB in the TB
> message doesn't match the negotiated keyparams, reject the bindings.
>
> Right, so there is no downgrade from what’s negotiated. Also, this
> prevents the client using parameters unsupported by the server.
>

For properly behaving clients, yes, but the server still has to check.

What's the risk or attack in a downgrade from what’s negotiated?

I'd like to better understand this one in particularly because the I-D I'm
intending to write about using TB with TLS terminating reverse proxies will
need to deal with the MUST somehow. I'm leaning towards having the
application validate the Token Binding Message with the EKM sent as a
header by the TLS terminator. That approach would seem to imply that the
application also check that the negotiated key parameters type matches
what's in the message. So that needs to be passed too. Which can be done
but it muddies things.

> ignore the lack of TB message (please let me know if you have an attack in

I don't have a attack in mind. It seems like it's also a downgrade from
what was negotiated.

> If this request has a bound token in it, existing language will require

Yes. But if tokens haven't yet been issued by the server and will be issued
now, they won't be bound.

---

From: Andrei Popov <[email-masked]>
Date: Wed, 21 Dec 2016 01:20:49 +0000

@Brian:

Ø  What's the risk or attack in a downgrade from what’s negotiated?
For the sake of an extreme example, if my server is configured to accept post-quantum NewHope6k key parameters, I don’t want to be downgraded to rsa768_pkcs1.5.
We don’t have this issue yet, but even today a server operator probably does not want to receive rsa2048_pkcs1.5 after negotiating ecdsap256, for efficiency reasons.

Ø  But if tokens haven't yet been issued by the server and will be issued now, they won't be bound.
Correct, so this is identical to the case of TB not having been negotiated.
In a distant future, we might get to a point where servers and/or clients won’t settle for a connection without TB.
For such servers and clients, it will make sense to reject requests without TB messages.

@Nick:

Ø  I don't have a specific attack in mind here (perhaps you could have a mitm that's negotiating TB but then stripping TB messages, but that seems like a worse attack than the mitm not negotiating TB at all). I made an assumption that a client that negotiates TB but then doesn't send a TB message in accordance with the application profile is buggy. If this is a bug, I think servers should fail to inter-operate with it to reduce the number of buggy TB implementations in the ecosystem.
Specifically, what language do you suggest and in which I-D(s)?

---

From: Nick Harper <[email-masked]>
Date: Tue, 20 Dec 2016 17:45:57 -0800

On Tue, Dec 20, 2016 at 5:20 PM, Andrei Popov <[email-masked]>
wrote:
>
>
>
> @Nick:
>
> Ø  I don't have a specific attack in mind here (perhaps you could have a
> mitm that's negotiating TB but then stripping TB messages, but that seems
> like a worse attack than the mitm not negotiating TB at all). I made an
> assumption that a client that negotiates TB but then doesn't send a TB
> message in accordance with the application profile is buggy. If this is a
> bug, I think servers should fail to inter-operate with it to reduce the
> number of buggy TB implementations in the ecosystem.
>

In TBPROTO section 3, there currently is language describing when a client
MUST and MUST NOT send a TB message. I'd add a sentence/paragraph after the
first paragraph in that section to say something like "A server SHOULD
reject an application protocol message that does not contain a Token
Binding message if the client and server successfully negotiated the use of
the Token Binding protocol.".

The second-to-last paragraph of TBNEGO section 4 clarifies "If the client
does not support the Token Binding protocol version selected by the server,
then the connection proceeds without Token Binding". I'd add to that "If
the server selects the same Token Binding protocol version sent by the
client, then the Token Binding protocol was successfully negotiated".

Given the wording that already exists in those two sections, I think it
would be reasonable for one to infer that it is reasonable for a server to
reject application protocol messages if TB was negotiated but a TB message
wasn't sent (e.g. by sending an HTTP 4xx response). Adding more language
makes this more clear, but I don't feel particularly strongly about this
issue.

---

From: Andrei Popov <[email-masked]>
Date: Wed, 21 Dec 2016 02:02:16 +0000

Ø  In TBPROTO section 3, there currently is language describing when a client MUST and MUST NOT send a TB message. I'd add a sentence/paragraph after the first paragraph in that section to say something like "A server SHOULD reject an application protocol message that does not contain a Token Binding message if the client and server successfully negotiated the use of the Token Binding protocol.".
This does not work, because TBPROTO does not require that the TB message be included in every application protocol message. TBPROTO only requires the TB message in the client’s first application protocol message (in the connection where TB is negotiated).

The requirement that each HTTP request has a TB message in it is specific to HTTPS. While this is wasteful, we have to do it because HTTP headers are per request, rather than affecting the entire connection (HTTP/2 reduces this waste by compressing headers).

---

From: Nick Harper <[email-masked]>
Date: Tue, 20 Dec 2016 18:07:21 -0800

That could be changed to "A server SHOULD reject a client's first
application protocol message...", and I think that fixes that problem.
However, that doesn't cover the case of other application protocol messages
lacking a TB message when the application profile (e.g. HTTPSTB) expects
there to be one. The intention is that if the client disobeys the MUSTs in
that first paragraph, then the server is fine to reject the message. (I was
hoping that "an application protocol message" instead of "any application
protocol message" would be vague enough to get around the first message vs
every message restriction, but that isn't the case.)

On Tue, Dec 20, 2016 at 6:02 PM, Andrei Popov <[email-masked]>
wrote:

> Ø  In TBPROTO section 3, there currently is language describing when a
> client MUST and MUST NOT send a TB message. I'd add a sentence/paragraph
> after the first paragraph in that section to say something like "A server
> SHOULD reject an application protocol message that does not contain a Token
> This does not work, because TBPROTO does not require that the TB message
> be included in every application protocol message. TBPROTO only requires
> the TB message in the client’s first application protocol message (in the
> connection where TB is negotiated).
>
>
>
> The requirement that each HTTP request has a TB message in it is specific
> to HTTPS. While this is wasteful, we have to do it because HTTP headers are
> per request, rather than affecting the entire connection (HTTP/2 reduces
> this waste by compressing headers).
>

---

From: Andrei Popov <[email-masked]>
Date: Wed, 21 Dec 2016 02:13:42 +0000

What if instead we say in HTTPSTB that if the server is configured to require TB, then this server MUST reject HTTP requests lacking TB headers?

This avoids:

1.       The issue of the first vs. subsequent requests;

2.       The corner-casing of servers negotiating the client-offered TB version vs. a lower TB version;

3.       The squishiness of SHOULD.

From: Nick Harper [mailto:[email-masked]]
Sent: Tuesday, December 20, 2016 6:07 PM
To: Andrei Popov <[email-masked]>
Cc: Brian Campbell <[email-masked]>; IETF Tokbind WG <[email-masked]>
Subject: Re: [Unbearable] (late, sorry) WGLC question on establishing the binding or not

That could be changed to "A server SHOULD reject a client's first application protocol message...", and I think that fixes that problem. However, that doesn't cover the case of other application protocol messages lacking a TB message when the application profile (e.g. HTTPSTB) expects there to be one. The intention is that if the client disobeys the MUSTs in that first paragraph, then the server is fine to reject the message. (I was hoping that "an application protocol message" instead of "any application protocol message" would be vague enough to get around the first message vs every message restriction, but that isn't the case.)

---

From: Brian Campbell <[email-masked]>
Date: Wed, 21 Dec 2016 08:22:51 -0700

On Tue, Dec 20, 2016 at 6:20 PM, Andrei Popov <[email-masked]>
wrote:

> For the sake of an extreme example, if my server is configured to accept
> post-quantum NewHope6k key parameters, I don’t want to be downgraded to
> rsa768_pkcs1.5.
>

Yeah, I know the gist of downgrade. I'm struggling to understand it in this
specific context of TB. Like who would do the downgrade between negotiation
and app messages. And how that might even be possible. And to the benefit
of whom.

---

From: Andrei Popov <[email-masked]>
Date: Wed, 21 Dec 2016 18:21:26 +0000

Ø  I'm struggling to understand it in this specific context of TB. Like who would do the downgrade between negotiation and app messages. And how that might even be possible. And to the benefit of whom.
A mismatch between the negotiated TB parameters and those used in the TB message could occur as a result of implementation defects (we’ve already seen some of this). This is to the benefit of no one, but I think a server should detect this.
As for malicious downgrade, perhaps a client could DOS an application server by sending TB messages signed using CPU-intensive algorithms, even if the server is only configured to accept an efficient algorithm (assuming the server does not perform the TB parameters check)?

From: Brian Campbell [mailto:[email-masked]]
Sent: Wednesday, December 21, 2016 7:23 AM
To: Andrei Popov <[email-masked]>
Cc: Nick Harper <[email-masked]>; IETF Tokbind WG <[email-masked]>
Subject: Re: [Unbearable] (late, sorry) WGLC question on establishing the binding or not

Yeah, I know the gist of downgrade. I'm struggling to understand it in this specific context of TB. Like who would do the downgrade between negotiation and app messages. And how that might even be possible. And to the benefit of whom.

---

From: Brian Campbell <[email-masked]>
Date: Wed, 21 Dec 2016 11:48:40 -0700

Fair enough. Thanks.

On Wed, Dec 21, 2016 at 11:21 AM, Andrei Popov <[email-masked]>
wrote:

> Ø  I'm struggling to understand it in this specific context of TB. Like
> who would do the downgrade between negotiation and app messages. And how
> that might even be possible. And to the benefit of whom.
>
> A mismatch between the negotiated TB parameters and those used in the TB
> message could occur as a result of implementation defects (we’ve already
> seen some of this). This is to the benefit of no one, but I think a server
> should detect this.
>
> As for malicious downgrade, perhaps a client could DOS an application
> server by sending TB messages signed using CPU-intensive algorithms, even
> if the server is only configured to accept an efficient algorithm (assuming
> the server does not perform the TB parameters check)?
>
>
>
> *From:* Brian Campbell [mailto:[email-masked]]
> *Sent:* Wednesday, December 21, 2016 7:23 AM
> *To:* Andrei Popov <[email-masked]>
> *Cc:* Nick Harper <[email-masked]>; IETF Tokbind WG <
> [email-masked]>
> *Subject:* Re: [Unbearable] (late, sorry) WGLC question on establishing
> the binding or not
>
>
>
>
>
>
>
> Yeah, I know the gist of downgrade. I'm struggling to understand it in
> this specific context of TB. Like who would do the downgrade between
> negotiation and app messages. And how that might even be possible. And to
> the benefit of whom.
>
>
>
>
>
>
>

---

From: Brian Campbell <[email-masked]>
Date: Wed, 21 Dec 2016 12:18:31 -0700

On Tue, Dec 20, 2016 at 7:13 PM, Andrei Popov <[email-masked]>
wrote:

> What if instead we say in HTTPSTB that if the server is configured to
> require TB, then this server MUST reject HTTP requests lacking TB headers?
>

I think that's implied. It might be some time before straight requiring TB
is viable but that's a deployment/policy decision and of course such a
deployment would reject HTTP requests w/ out TB headers.

The situation at hand is a more general server that will accept both TB and
non-TB but when the client and server both negotiate the same TB version
and then the client doesn't send the TB message. Looking at the drafts a
bit more again I see that TBNEGO §4
<https://tools.ietf.org/html/draft-ietf-tokbind-negotiation-06#section-4>
has:

   If the "token_binding" extension is included in the server hello and
   the client supports the Token Binding protocol version selected by
   the server, it means that the version and key parameters have been
   negotiated between the client and the server and SHALL be definitive
   for the TLS connection.

While HTTPSTB §2
<https://tools.ietf.org/html/draft-ietf-tokbind-https-07#section-2> has:

   Once a client and server have negotiated the Token Binding Protocol
   with HTTP/1.1 or HTTP/2 (see [I-D.ietf-tokbind-protocol] and
   [I-D.ietf-tokbind-negotiation]), clients MUST include the Sec-Token-
   Binding header field in their HTTP requests.

Taken together I think that could be read to say that an HTTP client that
offers TB 1.0 in the client hello and gets TB 1.0 in the server hello but
doesn't send the TB message with HTTP requests is not complying with the
spec and a server could reasonably choose to reject such requests.

Does that seem legit?

I suppose more text could be added or clarified but maybe it's good enough
as is.

---

From: Andrei Popov <[email-masked]>
Date: Wed, 21 Dec 2016 19:55:27 +0000

Ø  What if instead we say in HTTPSTB that if the server is configured to require TB, then this server MUST reject HTTP requests lacking TB headers?

Ø  I think that's implied. It might be some time before straight requiring TB is viable but that's a deployment/policy decision and of course such a deployment would reject HTTP requests w/ out TB headers.
I also think that it is implied, but I don’t mind making this explicit in HTTPSTB, if folks think it would be more clear.

Ø  Taken together I think that could be read to say that an HTTP client that offers TB 1.0 in the client hello and gets TB 1.0 in the server hello but doesn't send the TB message with HTTP requests is not complying with the spec and a server could reasonably choose to reject such requests.

Ø

Ø  Does that seem legit?
Yes, this makes sense. If my TB client implementation failed to send TB messages when TB is negotiated, I’d treat it as a bug (per TBNEGO §4<https://tools.ietf.org/html/draft-ietf-tokbind-negotiation-06#section-4>) and get it fixed.
I think it is not important to require that the server enforce this, if the server is configured to accept non-TB requests.

The important thing is that when an HTTPS server requires TB, it MUST fail requests that lack TB messages. I think it already follows from the specs, but don’t mind stating explicitly.

---

From: Nick Harper <[email-masked]>
Date: Wed, 21 Dec 2016 12:25:56 -0800

On Wed, Dec 21, 2016 at 11:55 AM, Andrei Popov <[email-masked]>
wrote:

>
>
> Ø  What if instead we say in HTTPSTB that if the server is configured to
> Ø  I think that's implied. It might be some time before straight
> requiring TB is viable but that's a deployment/policy decision and of
> course such a deployment would reject HTTP requests w/ out TB headers.
>
> I also think that it is implied, but I don’t mind making this explicit in
> HTTPSTB, if folks think it would be more clear.
>
>
>
> Ø  Taken together I think that could be read to say that an HTTP client
> that offers TB 1.0 in the client hello and gets TB 1.0 in the server hello
> but doesn't send the TB message with HTTP requests is not complying with
> the spec and a server could reasonably choose to reject such requests.
>
> Ø
>
> Ø  Does that seem legit?
>
> Yes, this makes sense. If my TB client implementation failed to send TB
> messages when TB is negotiated, I’d treat it as a bug (per TBNEGO §4
> <https://tools.ietf.org/html/draft-ietf-tokbind-negotiation-06#section-4>)
> and get it fixed.
>
> I think it is not important to require that the server enforce this, if
> the server is configured to accept non-TB requests.
>

I agree with Brian on this point - we don't need any more language in the
spec to say that if the versions match, then the client and server
definitively know that TB was negotiated.

>
>
> The important thing is that when an HTTPS server requires TB, it MUST fail
> requests that lack TB messages. I think it already follows from the specs,
> but don’t mind stating explicitly.
>

I also think this follows, and I don't have a preference one way or another
about adding more language to state that explicitly.

---

From: Brian Campbell <[email-masked]>
Date: Wed, 21 Dec 2016 13:41:07 -0700

As the one who started the thread I've come around to thinking that no
additional language is needed. For whatever that's worth. Thanks for
discussing it though.

On Wed, Dec 21, 2016 at 1:25 PM, Nick Harper <[email-masked]> wrote:

>
>
> On Wed, Dec 21, 2016 at 11:55 AM, Andrei Popov <[email-masked]
> > wrote:
>
>>
>>
>> The important thing is that when an HTTPS server requires TB, it MUST
>> fail requests that lack TB messages. I think it already follows from the
>> specs, but don’t mind stating explicitly.
>>
>
> I also think this follows, and I don't have a preference one way or
> another about adding more language to state that explicitly.
>
>