Subject: [TLS] Enforcing Protocol Invariants

From: David Benjamin <[email-masked]>
Date: Tue, 12 Jun 2018 12:27:39 -0400

Hi all,

Now that TLS 1.3 is about done, perhaps it is time to reflect on the
ossification problems.

TLS is an extensible protocol. TLS 1.3 is backwards-compatible and may be
incrementally rolled out in an existing compliant TLS 1.2 deployment. Yet
we had problems. Widespread non-compliant servers broke on the TLS 1.3
ClientHello, so versioning moved to supported_versions. Widespread
non-compliant middleboxes attempted to parse someone else’s ServerHellos,
so the protocol was further hacked to weave through their many defects.

I think I can speak for the working group that we do not want to repeat
this adventure again. In general, I think the response to ossification is
two-fold:

1. It’s already happened, so how do we progress today?
2. How do we avoid more of this tomorrow?

The workarounds only answer the first question. For the second, TLS 1.3 has
a section which spells out a few protocol invariants
<https://tlswg.github.io/tls13-spec/draft-ietf-tls-tls13.html#rfc.section.9.3>.
It is all corollaries of existing TLS specification text, but hopefully
documenting it explicitly will help. But experience has shown specification
text is only necessary, not sufficient.

For extensibility problems in servers, we have GREASE
<https://tools.ietf.org/html/draft-ietf-tls-grease-01>. This enforces the
key rule in ClientHello processing: ignore unrecognized parameters. GREASE
enforces this by filling the ecosystem with them. TLS 1.3’s middlebox woes
were different. The key rule is: if you did not produce a ClientHello, you
cannot assume that you can parse the response. Analogously, we should fill
the ecosystem with such responses. We have an idea, but it is more involved
than GREASE, so we are very interested in the TLS community’s feedback.

In short, we plan to regularly mint new TLS versions (and likely other
sensitive parameters such as extensions), roughly every six weeks matching
Chrome’s release cycle. Chrome, Google servers, and any other deployment
that wishes to participate, would support two (or more) versions of TLS
1.3: the standard stable 0x0304, and a rolling alternate version. Every six
weeks, we would randomly pick a new code point. These versions will
otherwise be identical to TLS 1.3, save maybe minor details to separate
keys and exercise allowed syntax changes. The goal is to pave the way for
future versions of TLS by simulating them (“draft negative one”).

Of course, this scheme has some risk. It grabs code points everywhere. Code
points are plentiful, but we do sometimes have collisions (e.g. 26 and 40).
The entire point is to serve and maintain TLS’s extensibility, so we
certainly do not wish to hamper it! Thus we have some safeguards in mind:

* We will document every code point we use and what it refers to. (If the
volume is fine, we can email them to the list each time.) New allocations
can always avoid the lost numbers. At a rate of one every 6 weeks, it will
take over 7,000 years to exhaust everything.

* We will avoid picking numbers that the IETF is likely to allocate, to
reduce the chance of collision. Rolling versions will not start with 0x03,
rolling cipher suites or extensions will not be contiguous with existing
blocks, etc.

* BoringSSL will not enable this by default. We will only enable it where
we can shut it back off. On our servers, we of course regularly deploy
changes. Chrome is also regularly updated and, moreover, we will gate it on
our server-controlled field trials
<https://textslashplain.com/2017/10/18/chrome-field-trials/> mechanism. We
hope that, in practice, only the last several code points will be in use at
a time.

* Our clients would only support the most recent set of rolling parameters,
and our servers the last handful. As each value will be short-lived, the
ecosystem is unlikely to rely on them as de facto standards. Conversely,
like other extensions, implementations without them will still interoperate
fine. We would never offer a rolling parameter without the corresponding
stable one.

* If this ultimately does not work, we can stop at any time and only have
wasted a small portion of code points.

* Finally, if the working group is open to it, these values could be
summarized in regular documents to reserve them, so that they are
ultimately reflected in the registries. A new document every six weeks is
probably impractical, but we can batch them up.

We are interested in the community’s feedback on this proposal—anyone who
might participate, better safeguards, or thoughts on the mechanism as a
whole. We hope it will help the working group evolve its protocols more
smoothly in the future.

David

---

From: Jana Iyengar <[email-masked]>
Date: Tue, 12 Jun 2018 16:25:01 -0700

I'm emerging from lurking to just say this: I think this is a fantastic
idea, and thank you for doing it.
FWIW and IMO, you're better off summarizing the codepoints you are using
and planning to use on a wiki somewhere instead of in registries, given the
timescales and the lifetime of these codepoints.

- jana

On Tue, Jun 12, 2018 at 9:28 AM David Benjamin <[email-masked]>
wrote:

> The workarounds only answer the first question. For the second, TLS 1.3
> has a section which spells out a few protocol invariants
> Of course, this scheme has some risk. It grabs code points everywhere.
> Code points are plentiful, but we do sometimes have collisions (e.g. 26 and
> 40). The entire point is to serve and maintain TLS’s extensibility, so we
> <https://textslashplain.com/2017/10/18/chrome-field-trials/> mechanism.
> We hope that, in practice, only the last several code points will be in use
> at a time.
>
> * Our clients would only support the most recent set of rolling
> parameters, and our servers the last handful. As each value will be
> short-lived, the ecosystem is unlikely to rely on them as de facto
> standards. Conversely, like other extensions, implementations without them
> will still interoperate fine. We would never offer a rolling parameter
> without the corresponding stable one.
>
> _______________________________________________
> TLS mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/tls
>

---

From: Yuhong Bao <[email-masked]>
Date: Wed, 13 Jun 2018 03:50:22 +0000

Personally, I understood when the ClientHello was changed to deal with TLS version intolerant servers, but disliked the middlebox changes in the ServerHello.

________________________________________
From: TLS <[email-masked]> on behalf of David Benjamin <[email-masked]>
Sent: Tuesday, June 12, 2018 9:27:39 AM
To: <[email-masked]>
Subject: [TLS] Enforcing Protocol Invariants

Hi all,

Now that TLS 1.3 is about done, perhaps it is time to reflect on the ossification problems.

TLS is an extensible protocol. TLS 1.3 is backwards-compatible and may be incrementally rolled out in an existing compliant TLS 1.2 deployment. Yet we had problems. Widespread non-compliant servers broke on the TLS 1.3 ClientHello, so versioning moved to supported_versions. Widespread non-compliant middleboxes attempted to parse someone else’s ServerHellos, so the protocol was further hacked to weave through their many defects.

I think I can speak for the working group that we do not want to repeat this adventure again. In general, I think the response to ossification is two-fold:

The workarounds only answer the first question. For the second, TLS 1.3 has a section which spells out a few protocol invariants<https://tlswg.github.io/tls13-spec/draft-ietf-tls-tls13.html#rfc.section.9.3>. It is all corollaries of existing TLS specification text, but hopefully documenting it explicitly will help. But experience has shown specification text is only necessary, not sufficient.

For extensibility problems in servers, we have GREASE<https://tools.ietf.org/html/draft-ietf-tls-grease-01>. This enforces the key rule in ClientHello processing: ignore unrecognized parameters. GREASE enforces this by filling the ecosystem with them. TLS 1.3’s middlebox woes were different. The key rule is: if you did not produce a ClientHello, you cannot assume that you can parse the response. Analogously, we should fill the ecosystem with such responses. We have an idea, but it is more involved than GREASE, so we are very interested in the TLS community’s feedback.

In short, we plan to regularly mint new TLS versions (and likely other sensitive parameters such as extensions), roughly every six weeks matching Chrome’s release cycle. Chrome, Google servers, and any other deployment that wishes to participate, would support two (or more) versions of TLS 1.3: the standard stable 0x0304, and a rolling alternate version. Every six weeks, we would randomly pick a new code point. These versions will otherwise be identical to TLS 1.3, save maybe minor details to separate keys and exercise allowed syntax changes. The goal is to pave the way for future versions of TLS by simulating them (“draft negative one”).

Of course, this scheme has some risk. It grabs code points everywhere. Code points are plentiful, but we do sometimes have collisions (e.g. 26 and 40). The entire point is to serve and maintain TLS’s extensibility, so we certainly do not wish to hamper it! Thus we have some safeguards in mind:

* We will document every code point we use and what it refers to. (If the volume is fine, we can email them to the list each time.) New allocations can always avoid the lost numbers. At a rate of one every 6 weeks, it will take over 7,000 years to exhaust everything.

* We will avoid picking numbers that the IETF is likely to allocate, to reduce the chance of collision. Rolling versions will not start with 0x03, rolling cipher suites or extensions will not be contiguous with existing blocks, etc.

* BoringSSL will not enable this by default. We will only enable it where we can shut it back off. On our servers, we of course regularly deploy changes. Chrome is also regularly updated and, moreover, we will gate it on our server-controlled field trials<https://textslashplain.com/2017/10/18/chrome-field-trials/> mechanism. We hope that, in practice, only the last several code points will be in use at a time.

* Our clients would only support the most recent set of rolling parameters, and our servers the last handful. As each value will be short-lived, the ecosystem is unlikely to rely on them as de facto standards. Conversely, like other extensions, implementations without them will still interoperate fine. We would never offer a rolling parameter without the corresponding stable one.

* If this ultimately does not work, we can stop at any time and only have wasted a small portion of code points.

* Finally, if the working group is open to it, these values could be summarized in regular documents to reserve them, so that they are ultimately reflected in the registries. A new document every six weeks is probably impractical, but we can batch them up.

We are interested in the community’s feedback on this proposal—anyone who might participate, better safeguards, or thoughts on the mechanism as a whole. We hope it will help the working group evolve its protocols more smoothly in the future.

David

---

From: Alessandro Ghedini <[email-masked]>
Date: Wed, 13 Jun 2018 19:06:03 +0100

On Tue, Jun 12, 2018 at 12:27:39PM -0400, David Benjamin wrote:
> <https://tlswg.github.io/tls13-spec/draft-ietf-tls-tls13.html#rfc.section.9..3>.

This looks interesting and I very much agree that we should do *somthing* to
try to avoid the pain we've seen with deploying TLS 1.3 for future versions.

We (Cloudflare) would be happy to help with developing and deploying it, and
see how the experiment goes (and maybe even help put a draft together if needed,
if that is the form this proposal will take).

Cheers

---

From: Daniel Migault <[email-masked]>
Date: Wed, 13 Jun 2018 15:15:51 -0400

I also support something is being done in this direction. I like the idea
of taking ephemeral non allocated code points.

What is not so clear to me is how GREASE prevents a buggy implementations
from behaving correctly for GREASE allocated code points, while remaining
buggy for the other (unallocated). code points.
Yours,
Daniel

On Wed, Jun 13, 2018 at 2:06 PM, Alessandro Ghedini <[email-masked]>
wrote:

> has
> Code
> We
> parameters,

---

From: David Benjamin <[email-masked]>
Date: Wed, 13 Jun 2018 16:29:59 -0400

Are you asking about this new proposal (which still needs an amusing name),
or the original GREASE mechanism?

The original GREASE mechanism was only targetting ClientHello intolerance
in servers. It's true that it uses specific values, and indeed there is
nothing stopping buggy implementations from treating them differently. The
thought then was ClientHello intolerance in servers is usually just
accidental. It takes a certain willful ignorance to forget the default in
your switch-case, and then go out of your way to special-case things,
rather than recheck the spec as to what you're supposed to do. It was also
meant to be lightweight (a one-time implementation cost and a one-time
allocation). It's imperfect, but it does seem to help with the problem.

This new proposal is targetting ServerHello intolerance problems. Rather
than fixing a set of values initially, it regularly rerolls random values
over time, with no fixed pattern. It should hopefully be more resilient to
this sort of misbehavior. On the flip side, it is more work to maintain and
only implementations that update sufficiently frequently can participate,
whereas, in theory, anyone could deploy the original GREASE.

On Wed, Jun 13, 2018 at 3:15 PM Daniel Migault <[email-masked]>
wrote:

> On Wed, Jun 13, 2018 at 2:06 PM, Alessandro Ghedini <[email-masked]
> > wrote:
>
>> > <
>> https://tlswg.github.io/tls13-spec/draft-ietf-tls-tls13.html#rfc.section.9..3
>> >.

---

From: Christopher Wood <[email-masked]>
Date: Wed, 13 Jun 2018 14:04:44 -0700

> if that is the form this proposal will take).

+1

We (Apple) are interested in experimenting with this as well. Would it
be possible for
participating servers to support multiple random versions
simultaneously? That would
help address potentially longer release cycles.

Best,
Chris

---

From: David Benjamin <[email-masked]>
Date: Wed, 13 Jun 2018 17:22:05 -0400

> help address potentially longer release cycles.

That's great to hear (both of you)!

Supporting multiple values should be easy. Any participating stack already
must support two variants of TLS 1.3, the standard one and this rolling
version. Going from two to several is an easy step, on client or server.
(For us, this machinery is all a remnant of the middlebox experiments we
ran.) We were expecting our servers to support a handful of values anyway
to account for our own release cycles. We can experiment with the exact
cadence and code point lifetimes based on who all wishes to do this and
what works.

(At the worst case, mismatch is fine as both sides will just negotiate the
standard TLS 1.3. But an individual connection only exercises the
ServerHello when both sides match, so we'll want to maximize matches.)

David

---

From: Daniel Migault <[email-masked]>
Date: Wed, 13 Jun 2018 20:12:22 -0400

The two mechanisms address different targets but overall I prefer the
design of the new proposal.
Yours,
Daniel

On Wed, Jun 13, 2018 at 4:29 PM, David Benjamin <[email-masked]>
wrote:

> Are you asking about this new proposal (which still needs an amusing
> name), or the original GREASE mechanism?
>
> On Wed, Jun 13, 2018 at 3:15 PM Daniel Migault <
> [email-masked]> wrote:
>
>> On Wed, Jun 13, 2018 at 2:06 PM, Alessandro Ghedini <
>> [email-masked]> wrote:
>>
>>> > so the protocol was further hacked to weave through their many
>>> defects..
>>>
>>> >

---

From: Kyle Nekritz <[email-masked]>
Date: Thu, 14 Jun 2018 00:28:50 +0000

I think there may be lower overhead ways (that don’t require frequent TLS library code changes) to prevent ossification of the ServerHello using a mechanism similar to the cleartext cipher in quic. For example, a client could offer an “anti-ossification” extension containing an identifier that corresponds to a particular key. The identifier->key mapping can be established using a couple of mechanisms, depending on the level of defense desired against implementations that know about this extension:
* static mapping defined in RFC
* periodically updated mapping shared among implementations
* negotiated on a previous connection to the server, similar to a PSK
This key can then be used to “encrypt” the ServerHello such that it is impossible for a middlebox without the key to read (though would not add actual confidentiality and would probably involve aead nonce-reuse). There’s a couple of options to do this:
* Simply replace the plaintext record layer for the ServerHello with an encrypted record layer, using this key (this would not be compatible with existing middleboxes that have caused us trouble)
* Put a “real” encrypted ServerHello in an extension in the “outer” plaintext ServerHello
* Send a fake ServerHello (similar to how we encapsulate HelloRetryRequest in a ServerHello), and then send a real ServerHello in a following encrypted record
All of these would allow a server to either use this mechanism or negotiate standard TLS 1.3 (and the client to easily tell which one is in use).

With the small exception of potentially updating the identifier->key mapping, this would not require any TLS library changes (once implemented in the first place), and I believe would still provide almost all of the benefits.

From: TLS <[email-masked]> On Behalf Of David Benjamin
Sent: Tuesday, June 12, 2018 12:28 PM
To: <[email-masked]> <[email-masked]>
Subject: [TLS] Enforcing Protocol Invariants

Hi all,

The workarounds only answer the first question. For the second, TLS 1.3 has a section which spells out a few protocol invariants<https://urldefense.proofpoint.com/v2/url?u=https-3A__tlswg.github.io_tls13-2Dspec_draft-2Dietf-2Dtls-2Dtls13.html-23rfc.section.9.3&d=DwMFaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=l2j4BjkO0Lc3u4CH2z7jPw&m=SaWplkxkbv9O_Z71HdE6L71vu2f7ovWWaEQrPRRbywc&s=F7IJ9Nac5Of_GCvBVk0_QhTplCJjoboBSemHl0pi1oM&e=>. It is all corollaries of existing TLS specification text, but hopefully documenting it explicitly will help. But experience has shown specification text is only necessary, not sufficient.

For extensibility problems in servers, we have GREASE<https://urldefense.proofpoint.com/v2/url?u=https-3A__tools.ietf.org_html_draft-2Dietf-2Dtls-2Dgrease-2D01&d=DwMFaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=l2j4BjkO0Lc3u4CH2z7jPw&m=SaWplkxkbv9O_Z71HdE6L71vu2f7ovWWaEQrPRRbywc&s=tcAlu2fEfkKjM2l4WBCCRosOGV3DMAQcHvh8Pe38K5w&e=>. This enforces the key rule in ClientHello processing: ignore unrecognized parameters. GREASE enforces this by filling the ecosystem with them. TLS 1.3’s middlebox woes were different. The key rule is: if you did not produce a ClientHello, you cannot assume that you can parse the response. Analogously, we should fill the ecosystem with such responses. We have an idea, but it is more involved than GREASE, so we are very interested in the TLS community’s feedback.

* BoringSSL will not enable this by default. We will only enable it where we can shut it back off. On our servers, we of course regularly deploy changes. Chrome is also regularly updated and, moreover, we will gate it on our server-controlled field trials<https://urldefense.proofpoint.com/v2/url?u=https-3A__textslashplain.com_2017_10_18_chrome-2Dfield-2Dtrials_&d=DwMFaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=l2j4BjkO0Lc3u4CH2z7jPw&m=SaWplkxkbv9O_Z71HdE6L71vu2f7ovWWaEQrPRRbywc&s=owCJbXs1BznTLdshoZZA1ho_g9w_m27PlfWut3dMRpM&e=> mechanism. We hope that, in practice, only the last several code points will be in use at a time.

David

---

From: Steven Valdez <[email-masked]>
Date: Thu, 14 Jun 2018 10:35:24 -0400

This scheme probably isn't sufficient by itself, since a middlebox just has
to be aware of the anti-ossification extension and can parse the server's
response by decrypting it with the known mapping (either from the RFC or
fetching the latest updated mapping), and then ossifying on the contents of
the 'real' ServerHello. To keep the ServerHello from ossifying, you'll need
to change the serialization and codepoints of the ServerHello at each
rolling version.

On Wed, Jun 13, 2018 at 8:29 PM Kyle Nekritz <[email-masked]> wrote:

> I think there may be lower overhead ways (that don’t require frequent TLS
> library code changes) to prevent ossification of the ServerHello using a
> mechanism similar to the cleartext cipher in quic. For example, a client
> could offer an “anti-ossification” extension containing an identifier that
> corresponds to a particular key. The identifier->key mapping can be
> established using a couple of mechanisms, depending on the level of defense
> desired against implementations that know about this extension:
> This key can then be used to “encrypt” the ServerHello such that it is
> impossible for a middlebox without the key to read (though would not add
> actual confidentiality and would probably involve aead nonce-reuse).
> There’s a couple of options to do this:
> * Simply replace the plaintext record layer for the ServerHello with an
> encrypted record layer, using this key (this would not be compatible with
> existing middleboxes that have caused us trouble)
> * Send a fake ServerHello (similar to how we encapsulate HelloRetryRequest
> in a ServerHello), and then send a real ServerHello in a following
> encrypted record
> All of these would allow a server to either use this mechanism or
> negotiate standard TLS 1.3 (and the client to easily tell which one is in
> use).
>
> With the small exception of potentially updating the identifier->key
> mapping, this would not require any TLS library changes (once implemented
> in the first place), and I believe would still provide almost all of the
> benefits.
>
> *From:* TLS <[email-masked]> *On Behalf Of *David Benjamin
> *Sent:* Tuesday, June 12, 2018 12:28 PM
> *To:* <[email-masked]> <[email-masked]>
> *Subject:* [TLS] Enforcing Protocol Invariants
>
> Hi all,
>
> has a section which spells out a few *protocol invariants*
> <https://urldefense.proofpoint.com/v2/url?u=https-3A__tlswg.github.io_tls13-2Dspec_draft-2Dietf-2Dtls-2Dtls13.html-23rfc.section.9.3&d=DwMFaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=l2j4BjkO0Lc3u4CH2z7jPw&m=SaWplkxkbv9O_Z71HdE6L71vu2f7ovWWaEQrPRRbywc&s=F7IJ9Nac5Of_GCvBVk0_QhTplCJjoboBSemHl0pi1oM&e=>.
> For extensibility problems in servers, we have *GREASE*
> <https://urldefense.proofpoint.com/v2/url?u=https-3A__tools.ietf.org_html_draft-2Dietf-2Dtls-2Dgrease-2D01&d=DwMFaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=l2j4BjkO0Lc3u4CH2z7jPw&m=SaWplkxkbv9O_Z71HdE6L71vu2f7ovWWaEQrPRRbywc&s=tcAlu2fEfkKjM2l4WBCCRosOGV3DMAQcHvh8Pe38K5w&e=>.
> This enforces the key rule in ClientHello processing: ignore unrecognized
> parameters. GREASE enforces this by filling the ecosystem with them. TLS
> 1.3’s middlebox woes were different. The key rule is: if you did not
> produce a ClientHello, you cannot assume that you can parse the response.
> Analogously, we should fill the ecosystem with such responses. We have an
> idea, but it is more involved than GREASE, so we are very interested in the
> TLS community’s feedback.
>
> our server-controlled *field trials*
> <https://urldefense.proofpoint.com/v2/url?u=https-3A__textslashplain.com_2017_10_18_chrome-2Dfield-2Dtrials_&d=DwMFaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=l2j4BjkO0Lc3u4CH2z7jPw&m=SaWplkxkbv9O_Z71HdE6L71vu2f7ovWWaEQrPRRbywc&s=owCJbXs1BznTLdshoZZA1ho_g9w_m27PlfWut3dMRpM&e=>
> mechanism. We hope that, in practice, only the last several code points
> will be in use at a time.
>

---

From: Kyle Nekritz <[email-masked]>
Date: Thu, 14 Jun 2018 17:13:05 +0000

That’s definitely a possibility if using a single key that never changes. With periodically rolling new keys, I’m not sure the risk is much different than with periodically rolling new versions. Ossifying on updated versions of either requires the middlebox to take a hard dependency on having the updated version available. Updating for arbitrary changes in the protocol is more complex than just updating a config for an encryption key, but I suspect we could also roll out an updated key mapping much faster than a new version that required TLS library code changes.

Using a negotiated key from a previous connection completely avoids that issue (for example the server sends an encrypted extension with identifier X and key Y, which the client remembers for future connections).

From: Steven Valdez <[email-masked]>
Sent: Thursday, June 14, 2018 10:35 AM
To: Kyle Nekritz <[email-masked]>
Cc: David Benjamin <[email-masked]>; <[email-masked]> <[email-masked]>
Subject: Re: [TLS] Enforcing Protocol Invariants

This scheme probably isn't sufficient by itself, since a middlebox just has to be aware of the anti-ossification extension and can parse the server's response by decrypting it with the known mapping (either from the RFC or fetching the latest updated mapping), and then ossifying on the contents of the 'real' ServerHello. To keep the ServerHello from ossifying, you'll need to change the serialization and codepoints of the ServerHello at each rolling version.

On Wed, Jun 13, 2018 at 8:29 PM Kyle Nekritz <[email-masked]<mailto:[email-masked]>> wrote:

From: TLS <[email-masked]<mailto:[email-masked]>> On Behalf Of David Benjamin
Sent: Tuesday, June 12, 2018 12:28 PM
To: <[email-masked]<mailto:[email-masked]>> <[email-masked]<mailto:[email-masked]>>
Subject: [TLS] Enforcing Protocol Invariants

Hi all,

David

_______________________________________________
TLS mailing list
[email-masked]<mailto:[email-masked]>
https://www.ietf.org/mailman/listinfo/tls<https://urldefense.proofpoint.com/v2/url?u=https-3A__www.ietf.org_mailman_listinfo_tls&d=DwMFaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=l2j4BjkO0Lc3u4CH2z7jPw&m=A0fyxW5rmTcvbMiTp9spH95BIoZV_kzN3a5WDFIeOMc&s=-W0PRTQvFVbCGrmO18_lHcSfZ_AdNYVjAyoPNhGpzwA&e=>