Modify client hello version when renegotiating to enhance interop with
authorDr. Stephen Henson <steve@openssl.org>
Thu, 9 Feb 2012 15:41:44 +0000 (15:41 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Thu, 9 Feb 2012 15:41:44 +0000 (15:41 +0000)
some servers.

CHANGES
ssl/s3_clnt.c

diff --git a/CHANGES b/CHANGES
index 9907aef8f35a5a47dea8d1eb5dbf96a387c72dfd..47d76cb81a0215d0075615f08a0019882d681ca2 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,13 @@
 
  Changes between 1.0.0f and 1.0.1  [xx XXX xxxx]
 
+  *) Some servers which support TLS 1.0 can choke if we initially indicate
+     support for TLS 1.2 and later renegotiate using TLS 1.0 in the RSA
+     encrypted premaster secret. As a workaround use the maximum pemitted
+     client version in client hello, this should keep such servers happy
+     and still work with previous versions of OpenSSL.
+     [Steve Henson]
+
   *) Add support for TLS/DTLS heartbeats.
      [Robin Seggelmann <seggelmann@fh-muenster.de>]
 
index ff1cff23d044dce56324186c93e81663819320f5..4511a914a43201921e55f4ef13ef4c35f6fd63f3 100644 (file)
@@ -689,9 +689,43 @@ int ssl3_client_hello(SSL *s)
                /* Do the message type and length last */
                d=p= &(buf[4]);
 
+               /* version indicates the negotiated version: for example from
+                * an SSLv2/v3 compatible client hello). The client_version
+                * field is the maximum version we permit and it is also
+                * used in RSA encrypted premaster secrets. Some servers can
+                * choke if we initially report a higher version then
+                * renegotiate to a lower one in the premaster secret. This
+                * didn't happen with TLS 1.0 as most servers supported it
+                * but it can with TLS 1.1 or later if the server only supports
+                * 1.0.
+                *
+                * Possible scenario with previous logic:
+                *      1. Client hello indicates TLS 1.2
+                *      2. Server hello says TLS 1.0
+                *      3. RSA encrypted premaster secret uses 1.2.
+                *      4. Handhaked proceeds using TLS 1.0.
+                *      5. Server sends hello request to renegotiate.
+                *      6. Client hello indicates TLS v1.0 as we now
+                *         know that is maximum server supports.
+                *      7. Server chokes on RSA encrypted premaster secret
+                *         containing version 1.0.
+                *
+                * For interoperability it should be OK to always use the
+                * maximum version we support in client hello and then rely
+                * on the checking of version to ensure the servers isn't
+                * being inconsistent: for example initially negotiating with
+                * TLS 1.0 and renegotiating with TLS 1.2. We do this by using
+                * client_version in client hello and not resetting it to
+                * the negotiated version.
+                */
+#if 0
                *(p++)=s->version>>8;
                *(p++)=s->version&0xff;
                s->client_version=s->version;
+#else
+               *(p++)=s->client_version>>8;
+               *(p++)=s->client_version&0xff;
+#endif
 
                /* Random stuff */
                memcpy(p,s->s3->client_random,SSL3_RANDOM_SIZE);