Subject: [TLS] Quest for Unified Solution to TLS Renegotiation

From: Michael D'Errico <[email-masked]>
Date: Wed, 25 Nov 2009 13:03:16 -0800

I think that it would be good to find a unified solution that
everybody is happy with, and believe that this may be it:

   1) Client-to-Server signalling can be done in either of
      two ways:

      A) an empty Secure_Renegotiation (SR) extension, or
      B) a "magic" cipher suite

   2) Server-to-Client signal is always an empty SR extension

   3) Incorporate previous verify_data into Finished calc.

The particulars:

A client that currently sends any other extensions MUST also
send the empty SR extension.

A client that currently does not send any extensions MAY send
the empty SR extension, or MAY send the magic cipher suite.

In response to either 1A or 1B, the server responds with an
empty SR extension.  The only ugliness is this apparently-
unsolicited extension returned by the server in response to
the magic cipher suite.  I used to be against this, but have
since decided that it is no more ugly than flipping a version
bit or any of the other ideas.

It remains to be decided if adding the verify_data to the
handshake message stream is the right way to do (3), or if
changing the PRF in some way is better, such as changing the
seed to be the handshake message hash appended with the old
verify_data, or some other method.

Benefits:

All versions including SSLv3 are fixed and able to renegotiate
safely.

This is entirely backward-compatible with SSLv3, even SSLv2
ClientHello.  It is better than RI because when the magic
cipher suite is used there, the server can not check the
verify_data from the client (since it is not sent), so it
can not renegotiate with those old clients at all.

Using an empty extension is much more lightweight a use of
extensions than RI since there is no need to pack the verify_
data into it when sending, or to extract the data when
receiving.

Clients that don't want to add full support for extensions do
not need to -- they can just check for the existence of the
empty SR extension which is a fixed 6-byte string.

I would fully support this "new"[*] solution.  Anybody else?

Mike

[*] I do not remember who initially came up with each of the
ideas in this solution; it was truly a team effort.

---

From: Marsh Ray <[email-masked]>
Date: Wed, 25 Nov 2009 15:37:36 -0600

>   3) Incorporate previous verify_data into Finished calc.

I like it!

> send the empty SR extension.

Is the server's behavior defined if he does not? E.g. alert message,
terminate, format C: /y, etc.

Wouldn't a robust implementation have to look out for that condition anyway?

Does this requirement amount to "this will never happen so you don't
have to bother testing for it (until your product hits the net)"?

> the empty SR extension, or MAY send the magic cipher suite.

Can he send both (is the 'or' inclusive)? What happens when the server
receives both?

Can a patched client send neither?

> empty SR extension.

The (patched) server MUST respond with ...

If the server does not respond with the extension the client MAY,
depending on external configuration, elect to continue the handshake
insecurely, or alert+abort (specifics).

The client SHOULD check that the extension_data is in fact empty (i.e.,
just its two length bytes of 00 00), and alert+aborting if not.

> The only ugliness is this apparently-

RFC 4346 (TLS 1.1) (and earlier versions)
http://tools.ietf.org/html/rfc4346#section-7.4.1.3
says Server Hello doesn't have extensions at all, yet it is updated by
RFC 4366 which adds them. What we are doing is no different AFAICT.

> verify_data, or some other method.

I think most people are comfortable with that approach.

Suggestions:

This extension applies equally to ALL handshakes on a single connection
regardless of whether they are an initial handshake or a renegotiation.

Client and server MUST negotiate the use of SR in the same manner
(including the choice of magic ciphersuite or Client Hello extension)
for all handshakes on a single connection.

Clients and servers SHOULD detect the case where the other party has
inconsistently negotiated the use of (or not using) SR and immediately
discard buffered data and alert+abort.

> All versions including SSLv3 are fixed and able to renegotiate

Hooray!

> can not renegotiate with those old clients at all.

Yippee!

> data into it when sending, or to extract the data when

It saves 24 bytes in each direction!

> empty SR extension which is a fixed 6-byte string.

Hard for anyone to complain about that, considering nobody was really
happy with the alternatives.

> I would fully support this "new"[*] solution.  Anybody else?

I support the solution!

Can we get the "bits on the wire" part drafted without unnecessary other
baggage?

- Marsh

---

From: Martin Rex <[email-masked]>
Date: Wed, 25 Nov 2009 23:05:56 +0100 (MET)

> the empty SR extension, or MAY send the magic cipher suite.

A client MUST send the magic cipher suite.  A client that sends
any TLS extension SHOULD send the the emtpy SR extension as well.

The server MUST check for the presence of the magic ciphersuite
and MUST use secure renegotiation when present.  The server
SHOULD NOT complain of absence of SR extension when the
magic ciphersuite is present.

-Martin

---

From: Stefan Santesson <[email-masked]>
Date: Wed, 25 Nov 2009 23:30:48 +0100

I support this.

I'm not sure whether the "magic" cipher suite MUST be present.
I think both approaches are acceptable but it feels like having it always
present may however offer better consistency after all and lead to simpler
test cases.

/Stefan

On 09-11-25 11:05 PM, "Martin Rex" <[email-masked]> wrote:

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

---

From: Eric Rescorla <[email-masked]>
Date: Wed, 25 Nov 2009 14:54:08 -0800

At Wed, 25 Nov 2009 13:03:16 -0800,
> everybody is happy with, and believe that this may be it:

This was actually suggested by Bodo Moeller last week.

>    2) Server-to-Client signal is always an empty SR extension

I just sent a message suggesting 1 and almost 2.

>    3) Incorporate previous verify_data into Finished calc.

I'm not happy with this, actually.

This requires breaking the current clean definition of handshake
hashes as the hash of all the handshake messages and simply adding
some synthetic message in the middle. I don't think this is anywhere
near as clean, as evidenced by the ongoing debate about whether to put
it the synthetic data in the front, the back, incorporate it into the
PRF, or chain the pre-existing handshake messages. [FWIW, I think I
prefer the last of these implicit versions.]

By contrast, RI allows that part of the system (which is well
understood) to remain the same and in fact when RI is offered on the
first handshake, there is no change to the TLS core at all. It's all
just hashed into Finished as part of the ordinary TLS procedures,
and everything is in fact compliant TLS, which I think is desirable.

I appreciate that this is to some extent a matter of tradeoffs,
but I don't find the arguments in favor of the implicit version
very compelling when weighed against the above.

-Ekr

---

From: Hovav Shacham <[email-masked]>
Date: Wed, 25 Nov 2009 15:16:12 -0800

On Nov 25, 2009, at 2:54 PM, Eric Rescorla wrote:

> some synthetic message in the middle.
> [...]
> first handshake, there is no change to the TLS core at all.

FWIW, I much prefer the RI approach.  It leverages more of the  
preexisting TLS machinery, which makes is easier to reason about and  
more likely not to break things.

Hovav.

---

From: Michael D'Errico <[email-masked]>
Date: Wed, 25 Nov 2009 15:19:51 -0800

> This was actually suggested by Bodo Moeller last week.

Yes, I just reread his message of Nov. 15 which states:

      One way to avoid most of the overhead from the current
      ID would be to keep the extension *always* empty.  If
      the client and server both send it during any given
      handshake, then the Finished messages concluding that
      handshake will be computed mostly in the standard way,
      but if it's a renegotiation handshake, including the
      previous handshake's Finished messages in the handshake_
      messages that will be hashed.  [Open question: Where
      should they go?  Maybe the easiest is to always hash
      them at the end; client first, server second.]

> I just sent a message suggesting 1 and almost 2.

Great, we are getting closer.

> very compelling when weighed against the above.

I think that moving forward to TLS 1.3 and beyond, we really want
the old verify_data incorporated directly into Finished, don't we?
Using an extension for this only makes sense because we need to
patch old versions.

The complaint I have about sending the verify_data over the wire is
that that alone does not plug the hole.  You need to take the extra
step to check that it's correct, and a maintenance programmer not
intimately familiar with TLS might miss this fact.

Changing Finished to the way we would like it in TLS 1.3 and beyond
seems like a better way to proceed.  Chaining the previous handshake
messages with the renegotiation does seem like a cleaner approach
than inserting the old verify_data into the handshake stream, so I'd
support that if that's the consensus.

Mike

---

From: Eric Rescorla <[email-masked]>
Date: Wed, 25 Nov 2009 15:24:45 -0800

At Wed, 25 Nov 2009 15:19:51 -0800,
> intimately familiar with TLS might miss this fact.

I don't find this argument very compelling. There are all sorts of
ways to screw up your TLS implementation that are worse than this
and are difficult/impossible to detect from the other side. E.g.,

- Weak randomness
- Failure to check buffers leading to buffer overflows
- Failure to check certs

TLS relies throughout on the assumption that the other side is
implemented more or less correctly. If we can't count on that,
we have bigger problems than this issue.

-Ekr

---

From: Martin Rex <[email-masked]>
Date: Thu, 26 Nov 2009 00:32:43 +0100 (MET)

> This was actually suggested by Bodo Moeller last week.

It's one of the options I summarized two weeks ago:

http://www.ietf.org/mail-archive/web/tls/current/msg04115.html

> prefer the last of these implicit versions.]

I *really* prefer this.  It's perfectly clean, and when doing it
right after ServerHello, it ends up at the same position
as if it was sent by the server in ServerHello.

> understood)

That change is certainly _not_ going to break anything
and well within the "well understood" domain.

I explained it here:
http://www.ietf.org/mail-archive/web/tls/current/msg04194.html

-Martin

---

From: Michael D'Errico <[email-masked]>
Date: Wed, 25 Nov 2009 16:25:04 -0800

> - Failure to check buffers leading to buffer overflows

My position is:  if we can avoid adding another one to this list,
then we should.

Mike

---

From: Martin Rex <[email-masked]>
Date: Thu, 26 Nov 2009 02:02:20 +0100 (MET)

> and are difficult/impossible to detect from the other side. E.g.,

The compelling reason is, that when we define TLSv1.3 then we
could stop sending the TLS extension RI entirely for TLS sessions
negotiated to use TLSv1.3.

If we use the band-aid TLS-extension-RI-with-verify-data to put the
verify data from the last handshake into the renegotiation, we will
need to contine apply this band-aid eternally.

-Martin

---

From: Martin Rex <[email-masked]>
Date: Thu, 26 Nov 2009 02:56:54 +0100 (MET)

> we have bigger problems than this issue.

If I look at the TLS renegotiation vulnerability,
then I think the SSLv3 designers who put renegotiation
in screwed it up in two ways:

  -  they didn't authenticate the enclosing TLS session
     in the renegotiation handshake.

  -  they used the exact same algorithm to authenticate
     initial authentications and renegotiations,
     and the result is that initial handshake can be
     proxied into renegotiations.

I think that we should not repeat either of these mistakes.

-Martin

---

From: Michael D'Errico <[email-masked]>
Date: Wed, 25 Nov 2009 19:50:27 -0800

>> I'm not happy with this, actually.

Would this work:

      Finished  =  verify_data  XOR  previous_verify_data

Not sure if anyone has suggested that already....

Does it work if you renegotiate twice or more times?

Also how to handle if renegotiation changes TLS version (SSLv3
verify_data is 36 bytes long).

Mike

---

From: David-Sarah Hopwood <[email-masked]>
Date: Thu, 26 Nov 2009 05:15:32 +0000

> bit or any of the other ideas.

I fully support this approach. The extension is not really
"unsolicited" in this case.

> verify_data, or some other method.

I previously argued for changing the use of the PRF in the Finished
computation, mainly in order to ensure that the possible PRF inputs
for modified and unmodified Finished computations would be disjoint.
However, that would have the disadvantage (pointed out by Bodo Möller)
that the data signed in any CertificateVerify message wouldn't include
the old verify_data, unless that were also explicitly changed.

The old verify_data should not just be appended to the handshake_messages
without any further encoding, though, because it might match the bytes
of some valid handshake message. In that case, there is the possibility
that a MITM might insert the old verify_data into the stream sent to
one peer, as though it were a handshake message. If that peer is using
the unmodified Finished computation (either because it is unpatched or
it is doing an initial handshake), then it may end up computing the same
Finished hash as the other peer that is using the modified computation.

I haven't gone through the details of this attack thoroughly enough
to be sure it will work, but it is too near working for comfort.

So, we could either:

1. Change the use of the PRF and also change CertificateVerify (if
   used):

    verify_data =
      PRF(master_secret, finished_label, Hash(handshake_messages)
                                         + previous_verify_data)
        [0..verify_data_length-1];

    struct {
        digitally-signed struct {
            opaque handshake_messages[handshake_messages_length];
            switch (is_renegotiation) {
              case false:
                  struct {};
              case true:
                  opaque previous_verify_data[previous_verify_data_length];
            };
        }
    } CertificateVerify;

2. Add the old verify_data to handshake_messages preceded by the encoding
   of a fatal alert. Then, attacks of the kind described above can't work
   because the unpatched peer would first process the alert and abort the
   handshake.

-- 
David-Sarah Hopwood  ⚥  http://davidsarah.livejournal.com

---

From: David-Sarah Hopwood <[email-masked]>
Date: Thu, 26 Nov 2009 05:35:21 +0000

> and everything is in fact compliant TLS, which I think is desirable.

This approach and RI have different security properties: because RI
does not change the Finished computation, it relies on the recipient
of the extension checking that its contents are correct.

OTOH, I think it's only necessary for the previous verify_data to
be sent once. So, how about sending that only in the ServerHello, i.e.

  1) Client-to-Server signalling:
       MUST send a "magic" cipher suite
       MAY send an empty Secure_Renegotiation (SR) extension (and
         SHOULD do so if it is sending other extensions).

  2) Server-to-Client signal MUST be a Secure_Renegotiation extension
     containing the previous client and server verify_data.
     A patched client MUST check this value.

  3) No change to Finished computation.

  4) A server that is doing a renegotiation MUST reject connections
     from clients that don't include the magic cipher suite.

- --

---

From: David-Sarah Hopwood <[email-masked]>
Date: Thu, 26 Nov 2009 05:41:21 +0000

>      Finished  =  verify_data  XOR  previous_verify_data

No. The previous_verify_data has to be in the input to the PRF
that also depends on the master_secret. If you just XOR it to
the output, then the attacker doesn't need to know the master_secret
in order to change the unmodified Finished to the modified one.

---

From: Martin Rex <[email-masked]>
Date: Thu, 26 Nov 2009 06:46:02 +0100 (MET)

> be sent once. So, how about sending that only in the ServerHello, i.e.

That is MUCH worse.

Normally the TLS handshake is symmetric, each one proves each other
(like with the Finished messages).

Client re-sending Client.Finished and Server re-sending Server.Finished
would still be symmetric (and both need to check).

If only one side sends and the other must check, then this is
asymmetric, and if the one side that is supposed to check
forgets it, then you have a security problem.

When each one resends. then both must forget to check to
make that security problem.

-Martin

---

From: Martin Rex <[email-masked]>
Date: Thu, 26 Nov 2009 06:50:18 +0100 (MET)

> to be sure it will work, but it is too near working for comfort.

There are no handshake messages after finished.

You forgot the signaling in the ServerHello and ClientHello
that is also covered by the handshake message hash.

the verify_data should be added directly following ServerHello.

-Martin

---

From: Yoav Nir <[email-masked]>
Date: Thu, 26 Nov 2009 08:24:20 +0200

What David-Sarah said, but you could XOR it with the master_secret as input to the PRF, or even better, use it instead of the finished_label.

This way, you don't have to worry about where to put it in the handshake message stream, just keep it from the previous session.

---

From: David-Sarah Hopwood <[email-masked]>
Date: Thu, 26 Nov 2009 06:55:59 +0000

> There are no handshake messages after finished.

That's not relevant.

> that is also covered by the handshake message hash.

It appears that
<http://www.ietf.org/id/draft-mrex-tls-secure-renegotiation-01.txt>
is indeed not vulnerable, because of the requirement that allow_old_renego
MUST be set to false when the peer is found not to be updated. Previous
summaries of the proposal on the list were not clear about this; they
implied that updating the finished hash would automatically make
renegotiations with an unupdated peer fail.

Note, however, that (unless it is changed as I suggested) this
contradicts one of the claimed advantages over RI.

> the verify_data should be added directly following ServerHello.

Yes, that's where the attacker would send it. (You may have been
confused by my choice of the word "appended"; I meant "appended at
the point where the it is known that the new Finished computation
will be used".)

---

From: Martin Rex <[email-masked]>
Date: Thu, 26 Nov 2009 08:35:37 +0100 (MET)

> to be sure it will work, but it is too near working for comfort.

OK.  you got a point!

It's true that there is a theoretical attack.

So Mikes idea to always add a length to the hash
(and therefore also change the initial handshake between
updated peers) was not so bad after all.

>    because the unpatched peer would first process the alert and abort the

Alerts are no handshake messages, so that doesn't work.

different possibilities:
  - add a bodyless-finished message to the beginning of the handshake
    message hash of a secure renegotiation before the ClientHello
    a position where the attacker can not insert handshake messages
  - add something different to both handshake message hashes
    before adding the verify_data to the renegotiation handshake
    message hash
  - frame the Client.Finished.verify_data plus
    Server.Finished.verify_data as a Finished message
  - signal initial and renegotiation handshakes differently in the
    handshake

-Martin

---

From: "Blumenthal, Uri - 0662 - MITLL" <[email-masked]>
Date: Thu, 26 Nov 2009 11:04:35 -0500

Yes, previous_verify_data MUST be a part of the input to the PRF. What Yoav
Nir said (XOR-ing it with the master_secret), should work (out of hand -
anybody sees a problem with it?).

    What David-Sarah said, but you could XOR it with
    the master_secret as input to the PRF, or even better,
    use it instead of the finished_label.

-- 
Regards,
Uri
<Disclaimer>

---

From: Martin Rex <[email-masked]>
Date: Thu, 26 Nov 2009 17:17:52 +0100 (MET)

I would really prefer the previous_verify_data to be covered by the
signature of the ClientVerify message.

It would be OK for me to add the verify_data of the Client.Finished
message to the renegotiation handshake before the ClientHello
(but the Server.Finished needs to go later, so that the
handshake roundtrip optimization is not killed by this).

-Martin

---

From: "Blumenthal, Uri - 0662 - MITLL" <[email-masked]>
Date: Thu, 26 Nov 2009 11:20:17 -0500

> signature of the ClientVerify message.

One does not exclude the other, does it?

-- 
Regards,
Uri         [email-masked]
<Disclaimer>

---

From: Marsh Ray <[email-masked]>
Date: Thu, 26 Nov 2009 10:33:10 -0600

> in order to change the unmodified Finished to the modified one.

If I understand it correctly, Mitm could decrypt the renegotiated
Finished message record, modify it, and re-encrypt it. Effectively this
means the authentication and integrity guarantees on protocol could be
no stronger than the encryption. That could be a significant weakening
of the protocol's security.

Another attack would require Mitm to arrange for an arbitrary Finished
message on the previous session.

In order to do that he would have to
a) know ahead of time what value to construct and
b) succeed at a first preimage attack on the hash function represented
by 12 bytes from the PRF

Pulling off (a) would be hard because of the unpredictable random_data
bytes in the other side's Hello message.

(b) would mean the protocol was so broken that he wouldn't need
renegotiation to compromise it. It's worth noting here that this hash
output is 96 bits. The NIST hash selection process for the successor to
SHA requires a minimum output size of 224 bits.

- Marsh

---

From: David-Sarah Hopwood <[email-masked]>
Date: Thu, 26 Nov 2009 17:23:06 +0000

> anybody sees a problem with it?).

The previous_verify_data is not necessarily secret, so this requires the
PRF to be secure against related-key attack. The particular PRFs used in
SSLv3 and TLS 1.0 to 1.2 should be secure in that sense, but (if we
decide to use this approach) I still prefer what I suggested before:

    verify_data =

which uses the PRF in a more conventional way.

---

From: David-Sarah Hopwood <[email-masked]>
Date: Thu, 26 Nov 2009 17:46:44 +0000

> Alerts are no handshake messages, so that doesn't work.

You're right, the attacker could just omit the alert.

>     a position where the attacker can not insert handshake messages

It's not clear to me that the attacker can't insert handshake messages
there. If an implementation normally ignores handshake messages with an
unrecognized HandshakeType, then it is likely to ignore them before the
ClientHello as well.

For a random 24-byte string, the HandshakeType has a 246 in 256 ~= 96%
probability of being unrecognized, but then the length is a uint24,
and the attacker needs it to encode the number 20 in order for the
attack to work as I described it. So this attack almost certainly isn't
practical, but we should be sure to prevent it rather than relying on
probabilities.

>   - signal initial and renegotiation handshakes differently in the

I'll have to think about these more carefully.

---

From: Martin Rex <[email-masked]>
Date: Thu, 26 Nov 2009 19:01:49 +0100 (MET)

> which uses the PRF in a more conventional way.

I strongly recommend against such an approach.
It's going to be a big mess implementation-wise.

You'll have to keep double the state around in order to be able
to calculate the Server.Finished of the Renegotiation, and
then transfer shift the oldest verify_data out after Server.Finished.

It's more code, it doesn't address the CertificateVerify at all
and to interop-test this reliably, you will need to perform
at least two rengotiations on a communication channel to be
sure that the shifting of the Finished messages works correctly.

Most implementations that offer renegotiation do not have
usage scenarios to test dual-renegotiations, requiring additional
test tools to be built.

One of the reasons why I wanted to add  the verify_data early
into the handshake is that the session only needs to provide
room for one of them, making it much easier to implement
when you don't have to special case around while
calculating the finished messages and temporarilyy parking
of the new Client.Finished before the new Server.Finished processing
has completed.

I think that adding the Client.Finished.verify_data at the very
beginning of a renegotiation handshake message hash,  maybe even prefixed
with a bogus Finished message header 0x14 0x00 0x00 0x77 would
address the theoretical attack that you brought up.

-Martin

---

From: Michael D'Errico <[email-masked]>
Date: Thu, 26 Nov 2009 10:06:11 -0800

There are a couple problems with changing the PRF:

    1)  there is no PRF in SSLv3
    2)  CertificateVerify is just a signature over the handshake messages

The idea of XOR'ing the verify_data with the master_secret would work
in SSLv3 (1), but would not help with (2).

Is (2) really important since the entire handshake is verified upon the
exchange of Finished messages?

Mike

---

From: "Blumenthal, Uri - 0662 - MITLL" <[email-masked]>
Date: Thu, 26 Nov 2009 13:11:35 -0500

I forgot about that. Good point. I agree.

As for SSLv3 - SMNP (Simply Not My Problem :). Would be nice to address it
as well, but I'd rather not bend over backwards to also fix SSLv3.

-- 
Regards,
Uri         [email-masked]
<Disclaimer>

---

From: David-Sarah Hopwood <[email-masked]>
Date: Thu, 26 Nov 2009 18:24:53 +0000

> unrecognized HandshakeType, then it is likely to ignore them before the

The TLS spec doesn't seem to be very clear on whether handshake messages
with an unrecognized HandshakeType must cause an error (section 7.4).
Does anyone know what implementations actually do?

> practical, but we should be sure to prevent it rather than relying on

Ah, but if the attacker makes ~17.5 million connections (which do not
all have to be to the same site; just to any site that they might want
to attack), then they can expect to get a previous_verify_data that
matches the encoding of a handshake message of unrecognized type.

---

From: Martin Rex <[email-masked]>
Date: Thu, 26 Nov 2009 19:31:53 +0100 (MET)

> unrecognized HandshakeType, then it is likely to ignore them before the

ClientHello is the first handshake message on a connection
that re-initialized the handshake message hash.
If an implementation doesn't get that correct, then it is
an obvious bug of the implementation.

As an additional safety feature, the finished label for
secure renegotiations could be modified.

> practical, but we should be sure to prevent it rather than relying on

I also believe it isn't practical to find a collision with a 24-byte
correctly encoded no-op handshake message (i.e. one that does not
adversly affect the handshake state), but if we can avoid it,
we should avoid it.

verify_data is not predictable, even for those TLS session where
the MitM is an original server or client. 

Thanks for identifying this issue, even when it currently
does not appear as a practical attack.

explicitly inserting the header of a finished message (0x14 0x00 0x00 0x19)
in front of the verify_data might help, because this is something that
an attack does not want to insert after a ServerHello handshake
message (oh yeah, one with an odd length field).

-Martin

---

From: Michael D'Errico <[email-masked]>
Date: Thu, 26 Nov 2009 10:36:48 -0800

> Does anyone know what implementations actually do?

My code will send a fatal unexpected_message alert.  This seems
like something that should be a MUST in the spec.

Mike

---

From: Martin Rex <[email-masked]>
Date: Thu, 26 Nov 2009 19:53:27 +0100 (MET)

> like something that should be a MUST in the spec.

Well.  I remember that a few years back when ASN.1 parsers were
attacked with random garbage, there was something called "asn1brute.c"
that would blindly send a ClientHello directly by a crafted
Certificate message and a lot of Servers would choke on the
ASN.1 of the certificate, including those who had not even
requested a client certificate with CertificateRequest.

There may be some unexpected slack in what kind of handshake
messages individual TLS implementations might process or
even accept in specific situations, where the protocol
doesn't define them to be valid.

An attitude "the finished message will split the good guys from
the bad ones" would not be advisable.

-Martin

---

From: David-Sarah Hopwood <[email-masked]>
Date: Thu, 26 Nov 2009 19:37:15 +0000

> One does not exclude the other, does it?

No. Changing both was option 1 in
<http://www.imc.org/ietf-tls/mail-archive/msg10718.html>.
I think this meets all of the cryptographic requirements; it's just
a matter of whether we can find anything simpler.

---

From: "Blumenthal, Uri - 0662 - MITLL" <[email-masked]>
Date: Thu, 26 Nov 2009 14:43:40 -0500

> a matter of whether we can find anything simpler.

Probably no we can't.

And it's about time we stopped arguing and started solidifying the solution.
:-) 
-- 
Regards,
Uri
<Disclaimer>

---

From: David-Sarah Hopwood <[email-masked]>
Date: Thu, 26 Nov 2009 19:53:15 +0000

Marsh Ray wrote:
> Finished message record, modify it, and re-encrypt it.
> Effectively this means the authentication and integrity guarantees on
> protocol could be no stronger than the encryption. That could be a
> significant weakening of the protocol's security.

The Finished messages are both encrypted and MAC'd, so to be more precise,
it would be dependent on the non-malleability of this authenticated
encryption. There is some redundancy in the SSL/TLS handshake design here;
it would be secure even if the Finished messages had not been encrypted
and MAC'd, for example. But there is no good reason to eliminate any part
of that redundancy.

---

From: Stephen Farrell <[email-masked]>
Date: Thu, 26 Nov 2009 20:03:35 +0000

On 26 Nov 2009, at 19:43, "Blumenthal, Uri - 0662 - MITLL" <[email-masked] 

> And it's about time we stopped arguing and started solidifying the  

+1

S.

---

From: Yoav Nir <[email-masked]>
Date: Fri, 27 Nov 2009 00:38:51 +0200

>> which uses the PRF in a more conventional way.

I don't see why my suggestion doesn't hold for SSLv3 as well. Here's from the spec:

enum { client(0x434C4E54), server(0x53525652) } Sender;

struct {
        opaque md5_hash[16];
        opaque sha_hash[20];
} Finished;

md5_hash
        MD5(master_secret + pad2 + MD5(handshake_messages +
                Sender + master_secret + pad1));

sha_hash
        SHA(master_secret + pad2 + SHA(handshake_messages +
                Sender + master_secret + pad1));

So this could be changed in renegotiation to the following, or the Sender field could be replaced with the contents of the previous Finished message (it's like the finished label)

enum { client(0x434C4E54), server(0x53525652) } Sender;

struct {
        opaque md5_hash[16];
        opaque sha_hash[20];
} Finished;

md5_hash
        MD5(master_secret^previous_Finished_message + pad2 + MD5(handshake_messages +
                Sender + master_secret + pad1));

sha_hash
        SHA(master_secret^previous_Finished_message + pad2 + SHA(handshake_messages +
                Sender + master_secret + pad1));

---

From: Nelson B Bolyard <[email-masked]>
Date: Thu, 26 Nov 2009 21:21:11 -0800

> anybody sees a problem with it?).

Yes.  In Hardware Security Modules that pass certain FIPS security levels,
and implement the PRF in hardware, a change to the use of the PRF that
causes data (non-key material) to get combined with key material (the master
secret) would require introduction of new paths, a big change, would take
at least a year to get all the approvals.

If you want to change inputs to the PRF, just keep keys separate from
non-key data.  Combine new non-key data with other existing non-key data
inputs, not with key data inputs.

---

From: Nelson B Bolyard <[email-masked]>
Date: Thu, 26 Nov 2009 22:00:36 -0800

>>>> Yes, previous_verify_data MUST be a part of the input to the PRF.
>>>> What Yoav Nir said (XOR-ing it with the master_secret), should work
>>>> (out of hand - anybody sees a problem with it?).

I replied to that in another message, but yes, don't mix key and non-key
data together like that in the PRF definition.  If you want to XOR the
new data with something, or append it to something, do it with some other
non-key (and non-constant) data that is input to the PRF, or else plan to
replace hardware.

>>> which uses the PRF in a more conventional way.

This would be OK for HSMs.  It doesn't change the definition of PRF.
It doesn't combine key and non-key data in a common input.
It doesn't change constants that may be in silicon.

On 2009-11-26 14:38 PST, Yoav Nir wrote:

> So this could be changed in renegotiation to the following, or the Sender
> field could be replaced with the contents of the previous Finished
> message (it's like the finished label)
>

For hardware security modules that implement SSL3, that change means
replacing the HSM.  The only change you can make to the definitions of
md5_hash and sha_hash that won't require the hardware to be replaced is
to change the definition of "handshake_messages".  That means somehow
making the additional data part of the data stream that gets input into
that MD5 or SHA function before "Sender", perhaps as if it was a pseudo
handshake message.

---

From: Martin Rex <[email-masked]>
Date: Fri, 27 Nov 2009 14:56:20 +0100 (MET)

> that MD5 or SHA function before "Sender", perhaps as if it was a pseudo

Which is one of the reasons why I'm favouring to expand the definition
of handshake messages for renegotiation and _NOT_ touch the PRF or
do other fancy stuff.  The one thing that SSLv3 and TLS have in
common is the concept of handshake message hash (a lot of other
stuff changed significantly).  The handshake message hash is
also the thing that goes into both, Finished and CertificateVerify.

-Martin

---

From: David-Sarah Hopwood <[email-masked]>
Date: Sat, 28 Nov 2009 01:08:51 +0000

I now agree that we should change handshake_messages, but I disagree
with something else you say below:

> sure that the shifting of the Finished messages works correctly.

This test (of a double-renegotiation) certainly should be done anyway.

---

From: David-Sarah Hopwood <[email-masked]>
Date: Sat, 28 Nov 2009 08:54:46 +0000

>>> which uses the PRF in a more conventional way.

I no longer think we should use this approach; the arguments in favour
of encoding the previous_verify_data in handshake_messages (see below)
are compelling.

[reordered]
>> As for SSLv3 - SMNP (Simply Not My Problem :). Would be nice to
>> address it as well, but I'd rather not bend over backwards to also
>> fix SSLv3.

SSLv3 is easy enough to fix without bending over backwards.

> I don't see why my suggestion [XORing the master_secret with the
> previous_verify_data when computing the new hashes] doesn't hold for
> SSLv3 as well.

It does, but the specification complexity is on the high side, given that
the computations would need to be spelled out for SSLv3 and TLS separately,
as well as changing CertificateVerify. Nelson's point about hardware
security modules is another reason not to do this.

Adding the previous_verify_data into handshake_messages is preferable
because:
 - it treats SSLv3 and TLS entirely uniformly;
 - there is no problem with hardware security modules;
 - the use of hashing APIs is unchanged (unlike the suggestion to
   chain all messages in the previous session before those in the
   current session);
 - it automatically causes the previous_verify_data to be included
   in the data signed by CertificateVerify, when used.

The obvious place to put it is just after ServerHello, since that is
before CertificateVerify and is the first point at which both sides
know that this session is renegotiated.

The theoretical attacks that I was worried about are solved by using
the encoding starting with bytes {20, 0, 0, 0} described in my
followup to Eric Rescorla (subject "Verify data in the RI extension" --
it doesn't seem to be in the archive yet).

---

From: Kyle Hamilton <[email-masked]>
Date: Sat, 28 Nov 2009 03:22:17 -0800

> prefer the last of these implicit versions.]

I would prefer to think in terms of "save the handshake hash values
after you verify them in Finished processing".  This would allow them
to be used as (essentially) initialization vectors for the next set of
handshake messages, thus providing "Message Authentication Code
continuity".  (The reason the attack works is because the server
doesn't properly authenticate the message, and the client can't know
that anything untoward happened.  The server doesn't chain any
information from the prior handshake into the current handshake, the
client doesn't chain any information from the prior handshake into the
current handshake, and there's no way for either the server or client
to tell the other exactly which negotiation epoch it thinks it's on.
If the prior handshake's information isn't chained in, from a security
standpoint it appears to be the same outcome as not verifying the MAC
on any given record.)  There shouldn't need to be any additional
verify_data sent, since all the information for ensuring that the same
client is talking with the same server is in those hashes.

So, potential ways to resolve this include:

1) including a 'negotiation epoch' in the handshake (if the server
thinks this is the first renegotiation, it's going to expect that the
epoch received from the client would be 1, not 0... and same for
subsequent negotiations).
2) Chain the last Finished hashes (NOT the master_secret or any key
material) as the initialization vector for the next handshake's
Finished MAC calculation.  (If you think about it, this is pretty much
the same as an epoch-based system, with each epoch 'named' by a
semi-random string of bits.)  Include the IV'd MAC as a field in the
Finished structure, and keep the current MAC calculation in place
(simply to simplify the lives of the vendors) -- which provides a
useful safety net: if they are the same, it's epoch 0, and if they're
not, it's not.

Now that we have some idea of how to authenticate the new session as
being an outgrowth of the prior, we now need to provide a means for
clients and servers that do this to notify each other that they're
using the modified handshake message algorithm.  We have on the table:

A) Secure Renegotiation Indicator TLS extension.
B) Magic cipher_suite.
C) Bit-fiddled version identifiers.

We are constrained by the following:

1) The mechanism for signalling must not screw up the protocol steps
for unpatched libraries.
2) The mechanism for signalling must be backward-compatible to SSLv3
(this is my interpretation of what the Area Director stated; please
correct me if I am wrong).

Because of constraint number 2, option A cannot be the mandated
mechanism for the client to signal the server that it supports
renegotiation continuity.  It is absolutely daft to try to turn an
integer into a bitfield, so option C is pretty much insane (and is
also fairly incompatible with DTLS, since its version is a
2s-complement of the TLS version it's based on).  This leaves option B
as the only sane mechanism that meets both constraints, for the client
to signal the server.

However, once the protocol is patched, it can be patched in any manner
the TLS group defines (and the TLS group has dominion over SSLv3, by
default, too).  So, the client's signal can tell the server that it's
okay to use a slightly different Finished message, no matter which
protocol version it's using -- one that includes a specific sequence
of bytes (a "magic number", if you will) after the end of the normal
Finished message.

Now, define the hash/PRF to have IVs of the prior iteration's Finished
hashes (each side has its own hash, so there's [a cryptographic
question: is there a reason to include both Finished hashes as IV
input to both the Server and the Client calculations?  Or should it be
sufficient to only include that side's prior hash?]  (the initial
vector for the first one is all bits clear), and you have a verifiable
chain of channel "ownership".

Am I misunderstanding the situation here?

> and everything is in fact compliant TLS, which I think is desirable.

The problem is this: all vendors -- not just a single vendor -- need
to be able to implement whatever's here *quickly*.  They need to do it
not just for TLS, but also for That Pre-TLS Protocol That Refuses To
Die.  There's no reason to change one in a manner that's incompatible
with the change made to the other.  (SSLv3 needs the magic cipher
suite, and that means that servers are going to have to support it if
they want to talk to even IE7 (which, IIRC, enabled SSLv3 but not
TLSv1.0).  SSLv3 ClientHello is still going to be used, and relying
only on an RI extension fails to support it.  Thus, it's pretty much a
non-starter.

As the Area Director has stated, the IETF is in this to ensure that
the network *works*, not to adhere to some ideologically 'pure'
concept.  SSLv3 is, unfortunately, going to have to be supported --
because if we suddenly break 75% of the clients on the network, not
only the users but IT admins and CTOs alike are going to be *pissed*.

An "unsolicited" empty RI extension from the server when it sees the
magic cipher_suite is probably the cleanest way to insert the
signalling required for any defense against the attack to work... the
server would not send it unless the client sent the magic ciphersuite
(or, following the TLS Extensions model, if the client offered it as
an extension during negotiation).  An unpatched server won't send the
RI extension even if the client sends the magic cipher_suite, so the
client should know not to renegotiate.  An unpatched client won't send
either the magic cipher_suite or the RI extension, so the server
should know not to renegotiate (and thus won't send the RI extension
-- again following the extensions model, with an addendum that the RI
extension is the only one that can be requested with a magic
cipher_suite being prepended to the actual list of ciphers that the
client's willing to use).

> very compelling when weighed against the above.

"Implicit version"?  There is no "implicit version" in the
Moeller/D'Errico proposal.  The version structure is never touched at
all.

-Kyle H

---

From: Eric Rescorla <[email-masked]>
Date: Sat, 28 Nov 2009 07:05:46 -0800

At Sat, 28 Nov 2009 03:22:17 -0800,
> Moeller/D'Errico proposal.  The version structure is never touched at

What's implicit is that the verify data is not explicitly carried
over the wire but implicitly inserted into the handshake hashes.

I agree that this isn't that great a name for the distinction.

-Ekr

---

From: David-Sarah Hopwood <[email-masked]>
Date: Sat, 28 Nov 2009 18:26:20 +0000

Kyle Hamilton wrote:
> renegotiation continuity.

That's not correct. Option A for S->C signalling works fine in SSLv3.
In the case where the server does not already support extensions, it's
just appending a fixed octet string to the ServerHello, so it is no
more difficult to implement than any other option.