Subject: [TLS] Final sanity checks on TLS

From: Eric Rescorla <[email-masked]>
Date: Wed, 11 Jun 2008 15:15:17 -0700

I was making my final Auth-48 pass on TLS and I ran into
two issues I wanted to raise:

1. In case of mismatch of the version number in the RSA encrypted PMS,
   the current draft, as suggested by Pasi, ends up with the server
   using the version number offered by the client, and overwriting
   those two bytes in the PMS. I.e.

   pre_master_secret = ClientHello.client_version || M[2..47]

   I don't see any immediate attack on this, but it gives me the
   willies, since in case of a mismatch, we're using a PMS that
   differs from the real PMS by only those two predictable bytes.
   I wonder if this could be used to probe the values a la Bleichanbacher.

   It seems to me that it would be safer to explicitly randomize the
   entire string. I.e.,

      1. Generate a string R of 46 random bytes

      2. Decrypt the message to recover the plaintext M

      3. If the PKCS#1 padding is not correct, or the length of
         message M is not exactly 48 bytes
            pre_master_secret = ClientHello.client_version || R
         else If ClientHello.client_version <= TLS 1.0, and
         version number check is explicitly disabled:
            pre_master_secret = M
         else:
            if version number matches:
              pre_master_secret = M
            else
              pre_master_secret = ClientHello.client_version || R

Thoughts?

2. S 7.4.6 reads:

      ecdsa_sign          ECDSA-capable public key; the certificate MUST
                          allow the key to be used for signing with the
                          hash algorithm that will be employed in the
                          certificate verify message; the public key
                          MUST use a curve and point format supported by
                          the server.

Unless I've missed something, in RFC 4492 the server doesn't advertise
the curves it knows, so this should be restated to be:
   
 the public key
                          MUST use a point format supported by
                          the server.

Note that this means that the client may provide a certificate the
server can't use, but that's a deficiency in 4492, ISTM..

Comments?
-Ekr

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

---

From: "Joseph Salowey (jsalowey)" <[email-masked]>
Date: Wed, 11 Jun 2008 16:07:31 -0700

Its hard for me to envision how the current algorithm could be exploited
in first issue, but it does seem to be a place where problems could
creep in. I would prefer to use the randomized string in the revised
text. 

For the second issue I agree that seems to be a deficiency in 4492.
The text seems accurate as it stands.  In order to interoperate the
client must present a certificate with a curve that the server can use;
the client just can't get this information from the server.  How big of
an issue is this in real deployments?  

Joe

> -----Original Message-----
> From: [email-masked] [mailto:[email-masked]] On 
> Behalf Of Eric Rescorla
> Sent: Wednesday, June 11, 2008 3:15 PM
> To: [email-masked]
> Subject: [TLS] Final sanity checks on TLS
> 
> I was making my final Auth-48 pass on TLS and I ran into two 
> issues I wanted to raise:
> 
> Unless I've missed something, in RFC 4492 the server doesn't 
> advertise the curves it knows, so this should be restated to be:
>    
>  the public key
> Note that this means that the client may provide a 
> certificate the server can't use, but that's a deficiency in 
> 4492, ISTM..
> 
> Comments?
> -Ekr
> 
> 
>

---

From: Eric Rescorla <[email-masked]>
Date: Wed, 11 Jun 2008 16:14:47 -0700

At Wed, 11 Jun 2008 16:07:31 -0700,
Joe Salowey wrote:
> the client just can't get this information from the server. 

Fair point. I could go either way on this change...

-Ekr

---

From: Mike <[email-masked]>
Date: Wed, 11 Jun 2008 16:20:16 -0700

>               pre_master_secret = ClientHello.client_version || R

In this situation, the goal is to have the connection fail (but not
right away), so a bogus premaster secret is used to generate the
master secret.  It seems to me that simply generating 48 bytes of
random data is the simplest way to achieve that.  What value is
there in taking the time to join the client_version to 46 bytes of
random data?  It's just wasted effort.

My code substitutes 48 bytes of random data for the PMS if the
decrypted PMS is not 48 bytes long or if the version in the PMS is
greater than the version extracted from ClientHello.  I don't think
it's necessary to enable/disable the check if done this way.

And actually I question the need for this check at all since it is
redundant.  If an attacker has modified the client hello to show a
lower version number, the Finished messages will not verify, and
the connection will fail.  DH exchanges don't have this feature,
and don't need it either.

Mike

---

From: Bodo Moeller <[email-masked]>
Date: Thu, 12 Jun 2008 01:52:16 +0200

>          version number check is explicitly disabled:

I don't see the point of specifying in a TLS 1.2 document this variant
where the version number check is disabled.  This case explicitly only
applies if the client speaks just TLS 1.0 and lower, and implicitly
only applies if the server speaks SSL 3.0 but not TLS 1.0!

(If you must include it, don't just ignore the version number included
in the encrypted premaster secret.  Instead it seems more prudent to
check that it's either one of those that you'd expect to see there,
i.e. either the version offered by the client [0x03 0x01] or the
version chosen by the server [0x03 0x00].)

>               pre_master_secret = ClientHello.client_version || R

There shouldn't be an actual problem with the

            premaster secret = ClientHello.client_version || M[2..47]

that draft-ietf-tls-rfc4346-bis-10.txt uses instead of comparing the
version number, but still I'd prefer to use the random bytes if the
numbers don't match -- this even is simpler, after all:

R is always prepared anyway, and you don't really need *two*
pseudocode lines both assigning randomness to pre_master_secret (you
can rearrange the control flow to use just one of these).

And why bother to include the actual value of ClientHello.client_version
when using R?  Why not use 48 random bytes for R?

>                           MUST use a point format supported by

True.

> server can't use, but that's a deficiency in 4492, ISTM..

This is intentional.  In the past, nothing in the TLS specification
has ever imposed explicit restrictions covering a complete certificate
chain -- which for complete coverage not only would have to provide
means to specify cryptographic capabilities of each party (which TLS
1.2 now does for hash and signature algorithms), but also which
critical X.509 extensions they can interpret, and a whole lot more.
You could include arbitrarily much of this in the handshake, but where
would you stop?

Fortunately, you usually don't need all this overhead anyway because
you'd choose CAs that are reasonable and tame when issuing
certificates.  TLS certificate verification even hopes that there's
just one public key for each distinguished name, at least for CAs, and
hoping that the certificates signed by your trusted CAs follow some
common pattern isn't too far off.  Specifically, many ECC CAs will
have all certificates signed by them use the same curve.  Others might
allow all kinds of curves, but you'd just picke these as preferred CAs
if you are able to verify whatever their policy allows -- just like
you would only pick CA if you agree with their policy regarding
critical extensions.  And if you are overly optimistic regarding some
CA's issuing policy, the worst that will happen is that you can't
verify a certificate: the handshake still can procede, just with
incomplete authentication.

Bodo

---

From: Bodo Moeller <[email-masked]>
Date: Thu, 12 Jun 2008 02:03:15 +0200

On Wed, Jun 11, 2008 at 04:20:16PM -0700, Mike wrote:

[...]
> and don't need it either.

The idea behind this check is that if there is some exploitable
weakness in protocol version x that has been fixed in version y
(y > x), you want to be able to prevent attackers from doing a
protocol downgrade attack if the client and server do both support the
y protocol.  I.e., the attacker would modify the client hello in
transmission to force the parties to use the weak x protocol,
for which we assume it could even forge the Finished messages.

Now it certainly doesn't seem that any current protocol version is
quite that bad.  Still, if you can rely on such a version check,
the analysis becomes simpler.

Bodo

---

From: <[email-masked]>
Date: Thu, 12 Jun 2008 18:34:25 +0300

>               pre_master_secret = ClientHello.client_version || R

The text in the current draft is based on the paper by Klima et al.,
Section 6.2 [KPR03]. It looks like Section 6.1.2 of the paper
describes the variation you're proposing, and the reasons why they
didn't choose that one.

Best regards,
Pasi