Subject: [TLS] One approach to rollback protection

From: Eric Rescorla <[email-masked]>
Date: Mon, 26 Sep 2011 16:44:18 -0700

I've been doing some thinking about how to prevent rollback to
TLS 1.0/SSLv3 from TLS 1.1-capable agents.

Since there's very little deployment of TLS 1.1+, basically anything
we do now will roll out more or less in parallel with TLS 1.1 deployment,
as long as it's backward compatible.The obvious technique here is to
stuff the relevant indicator in the cipher suites list, since we know that
servers ignore unknown entries there.

I've taken an initial crack at a draft for this:
http://svn.resiprocate.org/rep/ietf-drafts/ekr/draft-rescorla-tls-version-cs.txt

-Ekr

---

From: Eric Rescorla <[email-masked]>
Date: Mon, 26 Sep 2011 16:53:22 -0700

P.S. Yes, I know this is a big stinking hack.

---

From: Nico Williams <[email-masked]>
Date: Mon, 26 Sep 2011 19:13:21 -0500

> P.S. Yes, I know this is a big stinking hack.

So what, we've done the same sort of thing in SSHv2.  I say go for it.

Nico
--

---

From: Martin Rex <[email-masked]>
Date: Tue, 27 Sep 2011 02:21:33 +0200 (MEST)

> http://svn.resiprocate.org/rep/ietf-drafts/ekr/draft-rescorla-tls-version-cs.txt

My personal favourite would be to use an OR'ed bitmask, and we could
either "waste" a whole 256 cipher suite codepoints (or be more conservative
and require the reserved bits below to be all ZERO--requiring
only 16 cipher suite code points starting at a block boundary).

    version_major  = 0xYY (assigned/reserved by IANA as { 0xYY, * } )
    version_minor  = a set of 8 bits indicating TLS version offered by client

     x80|x40|x20|x10|x08|x04|x02|x01   Value
      7 | 6 | 5 | 4 | 3 | 2 | 1 | 0    Bit Position

      |   |   |   |   |   |   |   |
      |   |   |   |   |   |   |   | 
      |   |   |   |   |   |   |   `-  indicates SSLv3   support {0x03,0x00}
      |   |   |   |   |   |   `-----  indicates TLSv1.0 support {0x03,0x01}
      |   |   |   |   |   `---------  indicates TLSv1.1 support {0x03,0x02}
      |   |   |   |   `-------------  indicates TLSv1.2 support {0x03,0x03}
      |   |   |   `-----------------    (reserved for TLSv1.3)
      |   |   `---------------------    (reserved for TLSv1.4)
      |   `-------------------------    (reserved for TLSv1.5)
      `-----------------------------    (reserved for TLSv1.6)

    So a client offering SSLv3, TLSv1.0 an TLSv1.1
    would include cipher suite  { 0xYY, 0x07 }

    And a client offering TLSv1.0 and TLSv1.2 (but not SSLv3 and not TLSv1.1)
    would include cipher suite  { 0xYY, 0x82 }

-Martin

---

From: Eric Rescorla <[email-masked]>
Date: Mon, 26 Sep 2011 17:28:07 -0700

Hmm... What's the advantage of something this complicated/expressive,
especially given that there is no way to currently express
"I speak TLS 1.2 but not 1.0"?

My objective here isn't to replace the TLS version negotiation mechanism
but merely to remove the downgrade attack problem. If we get that right,
and there is WG interest in revamping the version system, we can do that at
some other time.

-Ekr

---

From: Martin Rex <[email-masked]>
Date: Tue, 27 Sep 2011 02:33:10 +0200 (MEST)

> P.S. Yes, I know this is a big stinking hack.

We've been seeing a significant delay in adoption of TLSv1.1.
So while it might smell like a dirty hack to some, I think it is a
reasonable approach to ease the transition pain for the installed base.

As it turned out, the TLS cipher suites were the only protocol extensibility
that had been really interop tested from the beginning, probably because the
list of cipher suites was already quite long when Netscape brought
SSLv3 to the IETF for standardization and most new implementors
started interop testing with much fewer cipher suites in their
initial implementations.

If you look at slowly IPv6 adoption is progressing, it looks like they
do not have enough "dirty hacks" in place yet.  :-]

-Martin

---

From: Eric Rescorla <[email-masked]>
Date: Mon, 26 Sep 2011 17:35:57 -0700

> do not have enough "dirty hacks" in place yet.  :-]

I tend to agree with you here... I was just
trying to preempt people telling me that using the cipher suites was ugly,
since I wholly agree with that criticism. I just figure it's ugly but necessary.

Best,
-Ekr

---

From: Martin Rex <[email-masked]>
Date: Tue, 27 Sep 2011 02:48:03 +0200 (MEST)

> "I speak TLS 1.2 but not 1.0"?

I know that with "current TLS version negotiation" it is not possible
to convey the exact protocol version that a clients supports or may
want to talk.

The issue with the original scheme is, that in order to offer TLSv1.2,
you MUST (de facto) implement *ALL* prior protocol versions.
But that currently means that you have to take all existing specs,
put them side-by-side and work out the diffs yourself, because
successors specs don't show the PDUs and semantics of previous
protocol versions side-by-side.

> and there is WG interest in revamping the version system, we can do that at

I don't think that revising the TLS version negotiation yet another
time is a sensible idea.  If we do it at all, make it right this
time.

It is really much more important to do the interop testing before
implementations of this are shipped, than making it the most
simplistic change possible in order to obtain a protected negotiation.

-Martin

---

From: Adam Langley <[email-masked]>
Date: Mon, 26 Sep 2011 20:56:43 -0400

> http://svn.resiprocate.org/rep/ietf-drafts/ekr/draft-rescorla-tls-version-cs.txt

In Table 1 you list TLS 1.1 twice.

It has been suggested by Yngve that the existing SSLv3, renego SCSV be
used to indicate TLS 1.0 support. That's something that I suspect we
will try.

> If the SCSV value is present and is not equal to ClientHello.client_version, then the server MUST terminate the handshake with a fatal "handshake_failure" alert.

This doesn't really make the deployment of new TLS versions that much
easier. The client would still have to try 1.2, 1.1, 1.0 etc. What
would be helpful is if the server, seeing a TLS 1.2 SCSV, treated the
client as if it has advertised 1.2.

Cheers

AGL

---

From: Eric Rescorla <[email-masked]>
Date: Mon, 26 Sep 2011 18:14:29 -0700

> protocol versions side-by-side.

I don't think I understand this: if you have a client which only wishes to
support TLS 1.2, what it currently does is to offer TLS 1.2 in the
ClientHello and then if the server selects a lower version in the
ServerHello, the client generates an error.

In an environment where the client could indicate any combination of
versions, the impact of implementing TLS 1.2 only would be that a
server which did not support TLS 1.2 would generate an error instead
of a ClientHello.

Since servers are supposed to select the highest common version, I'm
not sure I see serious difference between these two.

> time is a sensible idea.  If we do it at all, make it right this

I'm not sold that it's that lacking, other than the fact that people
have implemented
it wrong.

-Ekr

---

From: Eric Rescorla <[email-masked]>
Date: Mon, 26 Sep 2011 18:19:07 -0700

> In Table 1 you list TLS 1.1 twice.

My bad.

> client as if it has advertised 1.2.

That's certainly a possibility, but now we're actually substituting
the negotiation
mechanism with one based on smuggling it in ciphersuites, which is pretty gross.
Moreover, unless I'm missing something, this leaves the client unable to offer
extensions (since they often cause breakage as well) unless it has fallback,
at which point why not use fallback for version logic as well?

I see your point about trying sequentially, but I don't think the
situation is that
dire. It's probably reasonable to offer TLS 1.1 or 1.2 and assume that
TLS 1.1/1.2
stacks do TLS version negotiation properly. If that fails, fall back
aggressively
to SSLv3 or TLS 1.0 with nothing offensive like extensions.

Or am I missing something?
-Ekr

---

From: Martin Rex <[email-masked]>
Date: Tue, 27 Sep 2011 03:22:24 +0200 (MEST)

> In Table 1 you list TLS 1.1 twice.

2nd column in EKRs draft in front of [RFC5246]? probably simple typo.

And while in theory I do not see a need for a SSLv3 SCSV in EKRs
proposal, it would allow testing the processing of this SCSV
even before implementing TLSv1.2 -- because to test with some
amount of certainty you need your code to support at least
two different versions.

> used to indicate TLS 1.0 support. That's something that I suspect we

I'm confused.  SSLv3-only servers (or TLS Servers limited to SSLv3 for
whatever administrative reason) are explicitly allowed to support
TLS renegotiation!

If your client creates and persists longs lists of server properties
so that it may connect in the future without having to go through
a TLS handshake failure and app-level reconnect fallback, then
this may be of help.

The idea behind doing TLS version proposal through a TLS cipher suite
to allow simple TLS clients, that neither persist server feature
characteristics nor contain a reconnect fallback, to succeed
the TLS handshake and use TLSv1.1 without having to worry about
handshake failures from version-intolerant Servers (independent
of whether they choke on ClientHello.client_version > TLSv1.0
or whether they do an incorrect RSA premaster secret client_version check.

> 
> > If the SCSV value is present and is not equal to
> > ClientHello.client_version, then the server MUST terminate
> > the handshake with a fatal "handshake_failure" alert.
> 
> easier.

Correct, this requirement in EKRs proposal is quite counter-productive
to the problem and needs to be removed.

I would actually prefer not to see any "MUST abort" in that document...

> 
> The client would still have to try 1.2, 1.1, 1.0 etc. What

Correct.  The ClientHello.client_version = { 0x03, 0x01 } is sent
to keep the potentially version intolerant installed base working,
the TLS 1.1 or TLS 1.2 SCSV is sent to negotiate 1.1 or 1.2 with
peers supporting this scheme in spite of the conservative
ClientHello.client_version.

-Martin

---

From: Martin Rex <[email-masked]>
Date: Tue, 27 Sep 2011 03:35:52 +0200 (MEST)

Eric Rescorla wrote:
> the negotiation mechanism with one based on smuggling it in ciphersuites,
> which is pretty gross.

Now I'm somewhat puzzled.

Was your motivation to propose this only to ensure that a TLSv1.0,
SSLv3 or SSL Version 2 CLIENT-HELLO results in a fatal handshake failure
when both peers support higher than TLSv1.0?

I'm strongly opposed to that idea.

What I'm looking for is a protocol enhancements that will **IMPROVE**
TLS interop by having more TLS handshakes succeed.

> at which point why not use fallback for version logic as well?

No problem, TLSv1.1 and TLSv1.2 work just fine without extensions.
And if that is really an issue, an alternative would be to perform
a renegotiation directly after the handshake succeeded -- with the
added bonus that it incurs no handshake failure -- meaning that
it could be performed entirely within TLS and without involvement
of the calling application.

A handshake failure is a significant problem, since it always requires
the involvement of the application and a new network connection.

-Martin

---

From: Adam Langley <[email-masked]>
Date: Mon, 26 Sep 2011 21:38:20 -0400

> at which point why not use fallback for version logic as well?

What we want is the version negotiation that we're supposed to have.
But it broke :(

Let's say that NSS does TLS 1.2. We are probably only going to have
one level to fallback: to SSLv3, no compression. So servers which
currently do 1.0 or 1.1, but which are intolerant to a 1.2 client are
going to get SSLv3 instead. The last numbers that I saw from Yngve
were that these are ~2% of the Internet.

Not the end of the world, but we can avoid it if we advertise 1.0 in
the version and 1.2 with SCSV. Depends if the WG can stomach it :)

Cheers

AGL

---

From: Marsh Ray <[email-masked]>
Date: Mon, 26 Sep 2011 20:39:06 -0500

I agree that the current semantics are starting to feel a bit silly. 
Support for TLS 1.2 also implies a willingness to speak SSLv3?
Are we expecting to continue this forever?

>        7 | 6 | 5 | 4 | 3 | 2 | 1 | 0    Bit Position

But the current cipher suite negotiation is already a set. Why not just 
have one cipher suite value for each version and burn only 4 or so code 
points rather than 256?

On 09/26/2011 08:14 PM, Eric Rescorla wrote:
 > of a ClientHello. [ServerHello?]
 >

The difference is that somebody will look at Wireshark and instead of 
seeing random disconnects and thinking they're the subject of some 
low-level DoS attack, they'll see a bright yellow line that reads:
"TLS Alert: Endpoints support no common protocol version."

- Marsh

---

From: Juho Vähä-Herttua <[email-masked]>
Date: Tue, 27 Sep 2011 10:03:40 +0300

On Sep 27, 2011, at 4:39 AM, Marsh Ray wrote:
> I agree that the current semantics are starting to feel a bit silly. Support for TLS 1.2 also implies a willingness to speak SSLv3?

How come support for TLS 1.2 also implies a willingness to speak SSLv3? I don't see that in the specification.

> The difference is that somebody will look at Wireshark and instead of seeing random disconnects and thinking they're the subject of some low-level DoS attack, they'll see a bright yellow line that reads:

There is already a protocol_version alert, which is supposed to have exactly this meaning. If the client sends a lower version than the lowest supported server version in ClientHello, server replies with protocol_version alert. If the server sends a lower version than the lowest supported client version in ServerHello, client replies with protocol_version alert. Only problem here is that the version negotiation is broken in implementations, not that it doesn't work in theory...

The problem I believe Martin was trying to point out is a hypothetical case where a client for example supports TLS 1.1, TLS 1.2 and SSLv3 for backwards compatibility, but not TLS 1.0. When it connects to a server which supports SSLv3 and TLS 1.0 only, the server will most likely reply with TLS 1.0 in ServerHello. Now the client can only reply with protocol_version to indicate no common protocol version was supported, even though in fact SSLv3 handshake would have succeeded. Only way to fix this properly would be to explicitly list all supported versions in the ClientHello.

The suggestion brought up by Eric could make this possibly with only slight modifications, but then it would effectively override the current version negotiation. I can easily see a scenario where all implementations send TLS 1.0 in ClientHello and send all higher supported versions as cipher suites. That would be ugly, and I hate abusing the cipher suites for renegotiation and now this, but I have to admit it would solve a lot of problems...

About the current proposal by Eric I have to agree with Martin, it is a hack that only increases handshake failures without helping in any way with the current version negotiation problems. Implementing a proposal like that doesn't make much sense to me.

Juho

---

From: Nikos Mavrogiannopoulos <[email-masked]>
Date: Tue, 27 Sep 2011 09:07:54 +0200

> servers ignore unknown entries there.

How about servers that fail on unknown ciphersuites? (they used to 
exist). If such a thing is proposed there will be no incentive at all to 
fix the broken servers. I see Bill Frantz solution as a pragmatic one 
that does not break the protocol (a hack over hack makes the protocol so 
complicated that in a few years we'll need a clean slate redesign of 
TLS. Complexity adds security issues rarely solves them.).

regards,
Nikos

---

From: Yoav Nir <[email-masked]>
Date: Tue, 27 Sep 2011 11:26:04 +0300

>Are we expecting to continue this forever?

You don't have to speak SSLv3, but current semantics do say that you
advertise a range.  Yes, you are supposed to support the version in the
record header, the version in the ClientHello, and everything in between,
so you could probably do TLS 1.0 - TLS 1.2, and still interoperate with
most of the servers in the world. You could also do 1.1-1.2, but then
you're limited to an Internet with about 360 servers.

---

From: Dan Winship <[email-masked]>
Date: Tue, 27 Sep 2011 10:51:13 -0400

>    The natural defense against this attack is to have a "maximum
>    version" indicator which the client can safely send even to downrev
>    servers but which upgraded servers can check and will thus allow
>    downgrade detection.

You don't even need to indicate maximum version. The client just needs
to indicate "I've downgraded". Clients will never downgrade against a
server that implements version negotiation correctly, so if a compliant
server sees that flag, it knows there's an attack in progress.

-- Dan

---

From: Nikos Mavrogiannopoulos <[email-masked]>
Date: Tue, 27 Sep 2011 17:13:34 +0200

> server sees that flag, it knows there's an attack in progress.

The problem is that many servers support TLS 1.0 but they are so buggy 
(e.g. fail when seeing extensions or fail if padding in record packets 
exceeds the cipher block size) that clients downgrade in order to talk 
to them. In that case the server would see that as an attack. Adding 
such a protection could add more compatibility issues.

I think the goal should be to eliminate the need for downgrade and use 
the protocol negotiation of TLS.

regards,
Nikos

---

From: Badra <[email-masked]>
Date: Tue, 27 Sep 2011 17:40:20 +0200

Hi,

do the current TLS servers parse all the cipher suites received in the
ClientHello?

Best regards
Badra

On Tue, Sep 27, 2011 at 1:44 AM, Eric Rescorla <[email-masked]> wrote:

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

---

From: Matt McCutchen <[email-masked]>
Date: Tue, 27 Sep 2011 08:51:06 -0700

> mechanism with one based on smuggling it in ciphersuites, which is pretty gross.

You've already indicated your willingness to take hacks for better
functionality.

> Or am I missing something?

To clarify Adam's response: there are servers that tolerate TLS 1.0 +
extensions but not TLS 1.2, and clients would like to use TLS 1.0
against such servers.  They can achieve this on a first connection with
TLS 1.0 version + extensions + TLS 1.2 SCSV.  Without Adam's proposed
behavior, clients would need two stages of fallback in order to both use
TLS 1.0 with "semitolerant" servers and successfully connect to
completely intolerant servers.

-- 
Matt

---

From: Martin Rex <[email-masked]>
Date: Tue, 27 Sep 2011 22:32:38 +0200 (MEST)

Eric Rescorla wrote:
>
> I wrote:
> > 
> >  [ciphersuite minor value composed of bitmask]
>

Having slept over my own proposal (and considering the lack of interop
of the original TLS version negotiation demonstrated by the installed base),
I would be fine with a small set of simple cipher suite values, starting
with TLSv1.0.

My primary interests are

  - reducing the amount of failed TLS handshakes

  - allow TLS clients without reconnect fallback to propose
    TLSv1.1 or higher without risk of new interop failures with
    version intolerant servers or bugs related to RSA premaster secret
    client_version checks, such as the bug in Win7/Win2008R2 renego.

  - get protection for the TLS version negotiation for free
    (for peers that implement this)

Our implementation is unconditionally including the rfc5746 renego SCSV
in every ClientHello, so I don't see an interop issue with this.

Even sending TLS extension (which we do not) seems to be not much
of a problem these days.  But the number of interop problems that
we have noticed ourselves in TLS version negotiation, including incorrect
RSA premaster secret client_version checks, is very disappointing.

The changes necessary to add TLSv1.1 support to our implementation
looks pretty marginal, because it is essentially only the explicit
random IVs for TLS cipher suites with block ciphers in CBC mode
(plus removing the CBC-padding oracle, but already did that
 for all protocol versions).

But I would really like see a more robust TLSv1.1 negotiation
being standardized, because I don't see sending
ClientHello.client_version = { 0x03, 0x02 } as a viable option
due to the known interop problems for some more years.

-Martin

---

From: "Yngve N. Pettersen" <[email-masked]>
Date: Wed, 28 Sep 2011 23:17:48 +0200

Hi,

I am not sure I like this proposal, for several reasons:

- It does not protect against downgrades when connecting to older servers.  
(rather impossible to do that, of course)

- As noted, it is not protected against a compromised handshake integrity  
function of an older version, but I guess the handshake version could be  
changed in such a case.

- Forward compatibility. How does a X-year old server that support TLS 1.2  
understand that that new cipher suite code point is not some new cipher it  
does not support, but an indication that the client support TLS 1.5? The  
codepoints would have to not just be predictable, but the codepoints would  
also have to work for TLS NG using protocol version 4.1. How far ahead do  
we reserve codepoints, how much of the ciphersuite codepoint space will  
this eat up? Or do we assume that any TLS 1.2+ server is version and  
extension tolerant, so TLS 1.2 is the highest version we will ever need to  
assign a code point for?

- There is no way (at least in the draft) for the client to know that the  
server understands the SCSV, and processed it correctly. And I can see no  
possibility expect requiring the server to return a special extension  
signaling that, similar to the requirement for the Renego SCSV.

- How easy would it be for a server or client implementor to get it wrong?

- How does the server tell the client that it should always negotiated  
with the highest supported version when connecting? The server may send a  
fatal error, but it does not really tell the client what is wrong, or that  
it should be trying its highest supported version.

IMO The best way to stop version rollbacks occurring is to not allow them,  
at all. Unfortunately, however, for a time it will still be necessary, for  
interoperability reasons, to allow fallbacks if the server is intolerant.

That means finding, or declaring, that certain indications from the  
server, protected by the handshake hash, means that the server will not  
willingly require rollback to an older version.

This could be either a new extension (which runs up against the extension  
intolerance problem, and the possibility of an attacker faking the  
intolerance) or we could use an existing extension to indicate this.

As I have mentioned earlier, I think the second option is best, and that I  
think it already exists in the form of the Renego Indication (RI)  
Extension.

My suggestion is that when a client detects that a server have the RI  
extension, it MUST only use the highest configured version when connecting  
to that server. If a server not known to have RI triggers a fallback, and  
turns out to have RI support, it should immediately start using the  
highest supported version, and not fall back to an older version if the  
negotiation fails.

Sure, this is a bit of a hack, too, but it is one that can be deployed  
quickly (60+% of servers already support RI) without any further server  
updates, it need only be implemented client side, and the current server  
failure rate is less than 0.1% of all tested servers when signalling TLS  
1.1, TLS 1.2, or extensions (which is the major part of the failures),  
totaling only a few hundred sites in my sample (and I think these will be  
straightened out in short order once they start failing in all clients).

Any server that would implement a check for these SCSVs would (or should)  
also already:

   - Be extension tolerant
   - Be version tolerant
   - Implement the RI extension

If the RI is used as an indication of tolerance then the only way an  
attacker would be able to force a downgrade would be if he is able to fake  
the Finished message, a problem that this document admits also exists for  
the SCSV suggestion.

I therefore think using RI as an indicator will be a better solution  
(there is no perfect solution, unfortunately)

-- 
Sincerely,
Yngve N. Pettersen

********************************************************************
Senior Developer                     Email: [email-masked]
Opera Software ASA                   http://www.opera.com/
Phone:  +47 24 16 42 60              Fax:    +47 24 16 40 01
********************************************************************

---

From: Martin Rex <[email-masked]>
Date: Thu, 29 Sep 2011 00:57:05 +0200 (MEST)

Yngve N. Pettersen wrote:
> 
> I am not sure I like this proposal,

I'm very interested in a modified (=interop-improving)
version of this proposal.

> for several reasons:

This is no reason for, but also not an issue against it.

> function of an older version, but I guess the handshake version could be  

The existing TLS version negotiation can not protect against that either,
so this is not an issue against the proposal.

> extension tolerant, so TLS 1.2 is the highest version we will ever need to  

I do _not_ want to retire the original TLS version negotiation,
just like to see an alternative "hinting" being standardized to
accomodate a ~10 year transition period to get over TLS version-related
interop problems that exist in today's installed base.

The one thing that I want to see *RETIRED* by this proposal (and all future
updates/version of the TLS protocol) is client_version check on the
RSA premaster secret, because of the bugs in the installed base.

Assuming that the TLS WG produces at most 1 new TLS protocol version
every 2 years, and a 10 year transition period, SCSV values for
TLSv1.0 -> TLSv1.2 -> TLSv1.7 ought to be sufficient.

> signaling that, similar to the requirement for the Renego SCSV.

The natural place for the server response is ServerHello.server_version,
an element that exists in that PDU even in SSLv3.

Whether the server supports the SCSV is only interesting when the
SCSV is higher than ClientHello.client_version AND the server supports
a protocol version higher than ClientHello.client_version--and that
situation can be easily determined from the ServerHello.server_version
value.

> - How easy would it be for a server or client implementor to get it wrong?

Looking at the varying interpretations of what value the client_version
in RSA premaster secret should be checked against and the age of the
implementations that got this wrong -- EASY, I assume.

But if you take that as a measure, we would have to shut down the IETF.

If there is any hope at all (and I defy to give up that hope), let's
try to be clearer than the existing spec on _all_ details of the
version negotiation ("nanny spec"), and see how it works out.

Compared to rfc5746 renego, this proposal is "simple" on my scorecard.

> it should be trying its highest supported version.

The server does not do that.  The idea behind this proposal is that the
client can propose his highest supported (or actually the highest the
client is able and willing to use) TLS protocol version with no ill
side effects on the initial ClientHello.  There are _no_ requirements
to persist any knowledge for future connections.  That is quite similar
to the idea behind the rfc5746 renego SCSV.

Whether and when a TLS client sends version higher than TLSv1.0
in ClientHello.client_version is entirely up to the client.
We are _not_ suggesting to clients to change what they are
currently doing here.

In addition, I do _not_ know which of these ClientHellos is best:

1.  no TLSext, Record.version = 0x03,0x00, ClientHello.version = 0x03,0x00 
2.  no TLSext, Record.version = 0x03,0x00, ClientHello.version = 0x03,0x01 
3.  no TLSext, Record.version = 0x03,0x01, ClientHello.version = 0x03,0x01 
4.  SSL version 2 CLIENT-HELLO.version = 0x03,0x00
5.  SSL version 2 CLIENT-HELLO.version = 0x03,0x01

And would personally not recommend one over the other for clients
that have no reconnect fallback facility.

> willingly require rollback to an older version.

What I am seeing is that an increasing number of TLS clients *IS*
using reconnect fallbacks (all modern Browsers seem to do it),
and the reasons why they need to do them.  TLS version intolerance
and non-conforming RSA premaster secret client_version checks
is a significant problem.  TLS extension intolerance is another,
but for TLS clients that do not send TLS extensions at all,
this does not matter at all.

> intolerance) or we could use an existing extension to indicate this.

Using a TLS extension uses not only more bytes on the wire and is harder
to implement, it can not be used in any of the 5 cases above, so it
is not a practical alternative.

> highest supported version, and not fall back to an older version if the  

I strongly disagree.  A negotiation that will make the handshake fail
or require two handshakes instead of making the handshake succeed with
the desired result is not a negotiation, but a dirty hack -- even if
it uses elements of protocol PDUs "appropriately" and exactly as the
original design intended. 

TLS extension RI can not be used to repair the TLS version negotiation
which happens on the server side while parsing ClientHello and creating
ServerHello.  For this to work, the client must convey the TLS versions
it supports within ClientHello, in a fashion that upsets close to zero
of the installed base of servers and in a place that exists in all
PDUs to which the existing TLS clients with reconnect fallbacks are
willing to fallback to in case of unexpected connection closures
by the server.  Only in the latter case that band aid will be able
to protect the TLS version negotiation.

-Martin

---

From: Martin Rex <[email-masked]>
Date: Thu, 29 Sep 2011 04:22:25 +0200 (MEST)

> Compared to rfc5746 renego, this proposal is "simple" on my scorecard.

The real issue is not whether an implementor gets something wrong
(which can happen to every human being), but whether the implementor
ships an incorrect implementation that would have been caught by
sensible interop testing prior to shipment.

Doing a superficial, black-box interop testing with all default
settings is not much proof of anything and regularly insufficient.
Some amount of testing methodology is advisable.

(Maybe the IESG should require description of suitable interop test
 scenarios in protocol specifications--or an option to be removed
 from a spec?)
 
For complex entire protocols, testing all possible combinations
of options results in a combinatorial explosion (cartesian product
of all options) and is frequently quite unpractical.

But for testing individual protocol options (and negotiation thereof)
for interop, a cartesian product may be quite practical _and_
necessary to get any meaningful results.

I believe that the TLS version negotiation is a protocol option where
a more thorough interop testing is fairly practical and extremely valuable.

Basic complexity:

  1. max client TLS version >  max server TLS version
  2. max client TLS version == max server TLS version
  3. max client TLS version <  max server TLS version

Additional complexity: perform a renegotiation after (1), (2), (3).

To interop test the original TLS version negotiation
(i.e. Record.version, ClientHello.client_version
 and RSA PremasterSecret.client_version) the prerequisite
for full coverage is that both implementations have at
least two protocol versions in common.  common support for SSLv3&TLSv1.0
is already sufficient for a meaningful interop test!

One of (1), (2), (3) is going to be the result of
the default install.  The other two must be created
by tweaking the configuration of TLS client or TLS server
or both (enabling or disabling protocol versions)

Example:  interop testing openssl-1.0.0d client
          and and Win7+IIS 7.5 server

default config:  openssl-1.0.0d  implements SSLv3/TLSv1.0, offers TLSv1.0
default config:  Win7 implements SSLv3->TLSv1.2, TLSv1.2 disabled

Configure IIS 7.5 to request a client certificate (in order
to have renegotiation covered by the interop test)

initial test after default install represents scenario (3) above.

   openssl s_client -connect win7iis:443 -no_ssl2
     [--> ClientHello.client_version=TLSv1.0...]
     [<-- ServerHello.server_version=TLSv1.0...]
     [... initial handshake succeeds...]
     GET / HTTP/1.0<Enter><Enter>
     [<-- HelloRequest]
     [--> ClientHello.client_version=TLSv1.0...]
     [<-- ServerHello.server_version=TLSv1.0...]
     [...renegotiation handshake succeeds...]
     [...server reply for / ...]

In order to test scenario (1) and (2), disable protocol
versions TLSv1.0, TLSv1.1 and TLSv1.2 for Server of the SCHANNEL
Security Provider on the Win7/IIS machine and reboot.

testing scenario (1) from above:

   openssl s_client -connect win7iis:443 -no_ssl2
     [--> ClientHello.client_version=TLSv1.0...]
     [<-- ServerHello.server_version=SSLv3...]
     [... initial handshake succeeds...]
     GET / HTTP/1.0<Enter><Enter>
     [<-- HelloRequest]
     [--> ClientHello.client_version=SSLv3...]
     [<-- ServerHello.server_version=SSLv3...]
     [--> ClientKeyExchange+ChangeCipherSpec+Finished]
   ***** Win7/IIS-7.5 unexpectedly closes network connection.

testing scenario (2) from above:

   openssl s_client -connect win7iis:443 -no_ssl2 -ssl3
     [--> ClientHello.client_version=SSLv3...]
     [<-- ServerHello.server_version=SSLv3...]
     [... initial handshake succeeds...]
     GET / HTTP/1.0<Enter><Enter>
     [<-- HelloRequest]
     [--> ClientHello.client_version=SSLv3...]
     [<-- ServerHello.server_version=SSLv3...]
     [...renegotiation handshake succeeds...]
     [...server reply for / ...]

The unexpected termination of the network connection for interop
scenario (1) indicates a TLS version negotiation problem.

If you retry scenario (1) with other TLS/Web Servers, there is
no such interop problem. Even Windows2003/IIS 6.0 works just fine
in the same situation.

The interop problem with Win7/IIS-7.5 appears like an incorrect check
on the RSA premaster secret client_version on the renegotiation handshake.
Win7 SChannel appears to check against ClientHello.client_version
of the initial TLS handshake, while it ought to check (if at all)
against the ClientHello.client_version of the current TLS handshake.

This interop problem shows in exactly the same fashion when I use
an openssl-0.9.7d (17-Mar-2004) client, such as included in SLES-9sp3.
(btw. have I messed around too much with my Win7 machine, or does IIS-7.5
 really _not_ have insecure renegotiation disabled by default?).

An alternative TLS version negotiation scheme through SCSV 
for TLSv1.0 and above) results in a few more relevant test scenarios,
as does additional support for TLSv1.1 and TLSv1.2.  But I believe
the interop testing effort is still fairly manageable.

Would it be too much to ask implementors for interop-testing some
3 to 8 scenarios before shipping an implementation of the alternative
TLS version negotiation scheme, to ensure that everyone gets this
right before shipping this time?

-Martin

---

From: Nikos Mavrogiannopoulos <[email-masked]>
Date: Thu, 29 Sep 2011 08:38:11 +0200

> interop problems that exist in today's installed base.

For what reason? Since more and more people demand TLS 1.1 support more 
and more servers will make sure that they interoperate with it. Creating 
a new approach to negotiate versions might even create more 
interoperability problems. Why do you think implementers that got wrong 
the original simple negotiation will get right this one?

regards,
Nikos

---

From: Martin Rex <[email-masked]>
Date: Thu, 29 Sep 2011 17:00:28 +0200 (MEST)

Nikos Mavrogiannopoulos wrote:
> and more servers will make sure that they interoperate with it.

More and more browsers support reconnect fallbacks for version-intolerant
and extension-intolerant servers -- and since it is impossible to
protect against attackers forcing that fallback, a browser implementing
and offering TLSv1.1 is *NOT* a solution to the problem at all.

Firefox added the reconnect fallback although it supports at most TLSv1.0
and only has to deal with the comparatively small extension-intolerant
servers.  As soon as browsers start sending TLSv1.1 or TLSv1.1 in
ClientHello.client_version, they will be faces with the much more
serious TLS version intolerance problem, in particular with respect
to incorrect RSA premaster secret client_version checks.

So for browsers -- the only clients that are affected by BEAST-style
attacks besides SSL-VPNs, there currently is no robust protection
available.

>
> Creating a new approach to negotiate versions might even create more 

Lack of testing (methodology).

-Martin