Subject: [TLS] Suggestions regarding renego extensions, for present, future and old implementations

From: "Yngve N. Pettersen (Developer Opera Software ASA)" <[email-masked]>
Date: Mon, 16 Nov 2009 22:41:17 +0100

Hello all,

I've noticed there has been various suggestions about how one should add a  
signaling mechanism for clients and servers that does not support  
extensions in their current implementation.

As I understand it, the sticky point have been how the server can signal  
its patched status back to the client, so that both sides can be assured  
that the other end is patched and will use a secure renegotiation  
procedure.

Below is a suggestion for how to solve this problem.

Before I handle the older implementations I would like to suggest the  
following regarding the RI extension:

  1. The RI extension becomes mandatory for TLS 1.0 -> TLS 1.2 (inclusive)  
for handshakes that support Extensions at both ends

  2. That TLS 1.3+ handshakes ignore the RI Extension and instead  
automatically include data from the previous handshake on the connection,  
e.g. the finished messages as in the RI system, when calculating the  
finished messages, and other values, with the first handshake using a 0x00  
sequence matching the normal length of the value used in the calculation.  
These values should be included at some point in the handshake hash;  
either as a prefix or a postfix (I suspect a prefix may be easier to  
implement, the values are known as the handshake starts, and hashing can't  
start until the protocol version is known, anyway). Clients that know the  
server supports TLS 1.3 SHOULD NOT send the RI extension.

Regarding older implementations, since they have to be patched  
significantly anyway (if they are to be patched), I would suggest the  
following:

  A. The client signals patched status in a field that should not cause any  
trouble for servers; the suggested reserved cipher suite should be  
suitable for this

  B. This signal is, as far as the handshake is concerned, handled as if  
the client sent an RI extension field, so

  C. The server responds with an RI extension in the ServerHello, using the  
format specified for Extensions, using the finished messages from the  
previous negotiation on the connection, as specified in EKR's draft.

  D. When receiving the RI extension, the client must check that the values  
match what it expects, as with the RI, and fail the handshake if there is  
a mismatch

  E0. The Client then includes its finished data in the finished  
calculation at some point, possibly just by including it in the handshake  
hash after the ServerHello message, or concatenating it after all the  
other data before calculating the values that depend on the handshake hash.

  E1. An alternative to E0 is that a ciphersuite range is set aside to  
encode the entire client finished message as a sequence of "cipher  
suites", e.g (using 0xFE as a example)  (0xFE, len=N), (0xFE, fin00)  
(0xFE, fin01)  (0xFE, fin02) ... (0xFE, fin0N). Use of the ciphersuite  
series would then indicate the client's patched status, and it is  
automatically included in the handshake hash. The drawback is that this  
will make a range of 256 ciphersuite codepoints unavailable for future  
use. First handshake would code (0xFE, 0x00), the second for a 12 byte  
message (0xFE, 0x0C) (0xFE, fin0) ... (0xFE, finC). The sequence MUST be  
place at the end of the ciphersuite list.

  NOTE: A patched server that supports Extensions in the ClientHello MUST  
use that extension in the response, and ignore the fallback signal.  
Clients that detect that the server supports the RI extension directly  
SHOULD avoid sending the fallback signal in later handshakes.

IMO A-E should be relatively easy to implement both in clients and  
servers. Servers that normally does not support extension should be able  
to easily code the extension sequence and append it, and patched clients  
that does not support extensions normally should also be able to decode it  
easily, tough they should make sure they can read multiple extensions  
(just in case we have to do this again sometime)

The big issue I expect is the use of an extension in a Serverhello not  
preceded by a ClientHello using the extension is a departure from what is  
mandated by the Extension RFC. I think it can be defended as an exception  
due to the severity of this particular issue. As mentioned in B the idea  
is to consider the fallback signal as the extension.

It is possible that the extension ID in C should have a different assigned  
number than the normal RI extentsion so that clients that send both the  
extension and the fallback signal can tell which type of server they are  
negotiating with. This is particularly important if the background  
calculation update is used, instead of the ciphersuite finished message  
sequence, but IMO the client and server should use method 1 if they can,  
and method 2 when they are both TLS 1.3+ implementations.

A benefit of point C is that we avoid trying to modify exisiting  
ServerHello fields to something they were never designed for, and which  
might conceivably cause other problems.

And alternative to using the Extension in point C could be to allocate a  
separate handshake message sent immediately after the ServerHello (or at  
some other point before the HelloDone message), but I suspect that this  
would be more troublesome in some client implementation designs than  
looking for the extension sequence.

-- 
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: Tue, 17 Nov 2009 00:09:18 +0100 (MET)

> previous negotiation on the connection, as specified in EKR's draft.

One signaling mechanism that works for all is perfectly sufficient.
Two different signaling mechanism for the same purpose adds complexity
without value, and significantly complicates interop testing.

The signaling mechanism that can be blindly asserted, even when
performing extension-less ClientHello fallbacks as currently implemented
on Vista and in Firefox 3.5, reduces complexity.

When I suggested that the client always signals with a specially assigned
ciphersuite ID and the server should always respond with a ServerExtension
even when the client didn't send one, I received strong opposition,
since this would violate existing rules for TLS extensions.

I agree that this would be a significant change and might require
non-trivial changes to generic functions that deal with
TLS extensions processing in existing code.

>From a protocol perspective, however, I do not see a problem.

Just look at the one mandatory-to-implement TLS extension in
TLSv1.2 and its extremely weird implemenation and processing rules:

  - MUST be implemented by server
  - MAY be omitted by client using only default sig/hash algorithms
  - MUST be sent by client not capable/willing of default sig/hash algorithms
  - MUST NOT be sent by client proposing TLSv1.1 or older
  - MUST NOT be sent back in ServerHello

Looking at this mess, I'm wondering why this extension was deliberatly
crippled to not work with TLSv1.1.  Do we really want our TLS
implementations to replace negotiation by assumptions when someone
pulls the plug on SHA-1 based signatures?

I think it was previously mentioned on this list that the answer is,
that the Server reply for the signature_algorithms is through the
CertificateRequest message instead of a ServerHello extension
(a protocol change not known to TLSv1.1).

Bottom line, this would not be the first time that TLS extensions are
mutilated, TLSv1.2 signature_algorithms has set precedent already. :-/

> server supports TLS 1.3 SHOULD NOT send the RI extension.

Why not just change the finished calculation right away for all existing
protocol versions including SSLv3 and get rid of the TLS extension
on the renegotiation handshake entirely.  That is going to save
many lines of code, network bandwidth, protcol complexity and
pages in the TLSv1.3 spec describing this additional complexity.

> other data before calculating the values that depend on the handshake hash.

Perfectly sufficient.  There is no need to send the verify_data
of the finished messages over the wire.

The verify_data of the previous finished messages should go into the
handshake message hash always directly after ServerHello, so that it 
affects to CertificateVerify as well as other/future protocol extensions
that want to add additional handshake messages and might want to also
use the handshake message hash.

ClientHello and ServerHello is the negotiation mechanism for the
TLS base protocol (plus TLS extensions).  It is fairly unlikely that
any future protocol update will add handshake messages before them
and also unlikely that any future protocl update will remove
ServerHello. 

> place at the end of the ciphersuite list.

Please DON'T. 

I received the suggestion to have two special ciphersuites assigned
rather than one.  One to signal that the client is updated and the
other to signal whether the client is performing an initial handshake.

While this might sound nice, I do not believe it to really help anything.

The data in the plaintext phase of the handshake (i.e. all of ClientHello
and ServerHello) can be arbitrarily doctored by the MitM, and the
communication peers can only detect such doctoring when comparing
their handshake hashes, during verification of the finished messasges,
and additionally during CertificateVerify when client-authentication
is used.

If the finished message verification fails, it is difficult to tell
what caused it.  If we are debugging in a controlled environment,
such status indicators might help determining the cause.

In the presence of an attacker, everything is just a wild guess.

I consider it somewhat unlikely that a clients initial handshake
is proxied into a server renegotiation "by accident" and needs this
additional debugging hint.  ;-)

-Martin

---

From: Bodo Moeller <[email-masked]>
Date: Mon, 16 Nov 2009 15:24:58 -0800

[This message is really just saying "I agree" a lot.  Those who are  
just interested in seeing new arguments can safely skip it.]

> One signaling mechanism that works for all is perfectly sufficient.

I agree.

> From a protocol perspective, however, I do not see a problem.

Me neither.

Do we have any implementors who are worried about changes to existing  
code for TLS extension processing?  Yes, the change would introduce a  
new special case, but would this ever really be hard to handle?

> pages in the TLSv1.3 spec describing this additional complexity.

I agree.  We can just change the Finished calculation for handshakes  
where both parties send the signals indicating they support the  
updated protocol (e.g. said special ciphersuite ID, and said new  
server-side extension [which wouldn't have to carry any content,  
unlike in the current Renegotiation_Info proposal]).

> and also unlikely that any future protocl update will remove

Any new protocol version with such changes (which are very unlikely to  
begin with) would just have to define its own way of computing  
Finished messages such that the previous Finished messages are taken  
into account.

> While this might sound nice, I do not believe it to really help  

I agree.

Bodo

---

From: "Yngve N. Pettersen (Developer Opera Software ASA)" <[email-masked]>
Date: Tue, 17 Nov 2009 01:14:38 +0100

> pages in the TLSv1.3 spec describing this additional complexity.

The reason for not just changing the finished calculation in the  
background for pre-TLS 1.3 is that clients and servers using TLS 1.2 and  
earlier (including SSLv3) must be able to tell, during the *first*  
handshake, whether or not the other side is using the safe renegotiation  
method, while still being able to complete negotiation with an unpatched  
client or server during a transition period.

IMO The best way to accomplish that goal (in pre-TLS 1.3) is by including  
the chaining information in the handshake through the handshake messages.  
The question is how? My preference is to use the RI extension whenever  
possible in pre-TLS 1.3, since it is cleaner protocol-wise, with a  
fallback option on the client side if extensions are, or may be  
unavailable. I think most of the logic in pre-TLS 1.3 will surround the  
decisions to send and detect the fallback, the data of which would then be  
passed on to the RI processing (case E1), there would be little or no  
logic in the Finished message processing that is not required by the RI  
extension.

-- 
Sincerely,
Yngve N. Pettersen

---

From: Martin Rex <[email-masked]>
Date: Tue, 17 Nov 2009 02:28:57 +0100 (MET)

> client or server during a transition period.

Maybe you're slightly confused by the parallel discussions on the list.

*I* want to change only the finished message calculation for the
renegotiation handshake, and if you signal through ClientHello
and ServerHello, then you can determine with ease after sending
the ServerHello (client) or after processing the ServerHello (client)
whether a fallback to old-style renegotiation should be permitted
(per configuration/app steering) or whether the verify_data
of the finished messages from the previous handshake should
be added to the handshake message hash.

Extending the previously made example for OpenSSL 0.9.8g
to include a configuration option for backwards compatibility:

Server Side: s3_srvr.c:ssl3_send_server_hello()

        return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));

would have to be change to something like:

        ret = ssl3_do_write(s,SSL3_RT_HANDSHAKE);
        if ( ret>0 && s->s3->renegotiate ) {
            if ( !s->s3->patched_client_flag ) {
                if ( 0==(s->options & SSL_OP_ALLOW_INSECURE_RENEGOTIATE) ) {
                    ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
                    ret = -1;
                }
            } else {
                /* add previous verify_data of client.finished */
                ssl3_finish_mac(s,s->s3->peer_finished_md,
                                  s->s3->peer_finished_md_len);
                /* add previous verify_data of server.finished */
                ssl3_finish_mac(s,s->s3->finished_md,
                                  s->s3->finished_md_len);
           }
        }
        return(ret);

> possible in pre-TLS 1.3, since it is cleaner protocol-wise,

We are NOT adding an optional extension to TLS!
In TLSv1.0  (and spec-wise even TLSv1.1) TLS extension is something
entirely optional, and we are trying to build a fix for the base
protocol that should be as close to mandatory as possible for
protocols that we have finalized many years ago.

This defect TLS is an exception.  I do not expect that we need to fix
flaws in the TLS base protocol on a regular basis in the future
(at least I strongly hope so).

If we want implementors to hotfix this as quickly as possible
underneath as many unchanged apps as possible, then why do you
have such a significant problem to add it to existing protocols
with as little contortions as possible.

If we think that adding this to the TLSv1.3 base protocol instead
of carrying it around through extensions eternally, then we can
just do it right and fix the existing protocols in just the
same fashion.

It is easier, less code, less explaining, less confusion.
It should have been there all the time.

How do think people would have fixed this problem when it had
been found in 1998 or 2000?  By inventing TLS extensions first and then
asking everyone to implement it?  I really don't think so.

Please, put this fix were it belongs, where it should go in TLSv1.3
and where it should have been since 14 years in SSLv3,TLSv1.0,TLSv1.1
and TLSv1.2

-Martin