I am trying to add TLS 1.1 and 1.2 support to a packet capture product which already has TLS 1.0 support.

I have used Wireshark to capture traffic between my browser and an openssl server to generate some test cases. I have seen an unexpected TLS version flowing in all the traces I have created.

Secure Sockets Layer
    TLSv1.2 Record Layer: Handshake Protocol: Client Hello
        Content Type: Handshake (22)
        Version: TLS 1.0 (0x0301)
        Length: 105
        Handshake Protocol: Client Hello
            Handshake Type: Client Hello (1)
            Length: 101
            Version: TLS 1.2 (0x0303)

The above is an extract from one of the TLS 1.2 traces as reported by Wireshark. The version given is TLS 1.0 in the ClientHello and 1.2 in all subsequent messages. This happened in both the TLS 1.1 and 1.2 traces.

Appendix E.1. (Compatibility with TLS 1.0/1.1 and SSL 3.0) from the TLS 1.2 RFC says:

Earlier versions of the TLS specification were not fully clear on
what the record layer version number (TLSPlaintext.version) should
contain when sending ClientHello (i.e., before it is known which
version of the protocol will be employed).  Thus, TLS servers
compliant with this specification MUST accept any value {03,XX} as
the record layer version number for ClientHello.

That in itself is also a little ambiguous to me.

So my questions are:

  • Can this field be a completely arbitrary value (as long as it is SSLv3 or higher)?
  • Will the behaviour change depending on the version given in this field?
  • Is there some significance to the browser choosing TLS 1.0 rather than SSLv3?


1 Answer 1


Version fields occur in three places:

  • as part of the header for each record that the client and the server send;
  • as part of the ClientHello message from the client;
  • as part of the ServerHello message from the server.

Protocol Version Negotiation

The version field in the ClientHello is the maximum version supported by the client implementation. For instance, when the client puts 0x0302 in this field (that's the conventional value meaning "TLS 1.1"), the client tells the server: "I am ready to handle all protocol versions up to TLS 1.1". The version field in the ServerHello message from the server specifies which protocol version will be used for this connection. The server should use the highest protocol version that both client and server support.

The client should not announce support for a protocol version that it does not actually support, lest a server would choose such a version, mistakenly believing that the client indeed supports it.

About Records

The ClientHello from the client is sent wrapped into one or several records, and each record contains the protocol version as well. The records are like the envelopes around letters. It is safe to use version 0x0300 (SSLv3) for these records, regardless of the maximum supported version indicated in the ClientHello; that's like sending a letter in an SSLv3 envelope, but the letter says "by the way, I also support TLS 1.0 and TLS 1.1". Using SSLv3 records maximizes interoperability with old and buggy implementations who know only of SSLv3 and would reject records with a higher version.

The response from the server states the protocol version which will be used, and should come as records bearing that version. E.g. if the server says "TLS 1.1" in its ServerHello then that ServerHello should come wrapped into a record also tagged as "TLS 1.1"; and all subsequent records from both client and server should use that version.


Theoretically, a server should accept any value greater than or equal to 0x0300 in a version field, and should not complain if it contains, e.g. 0xA7C0 (meaning "TLS 165.193", a fictitious version which will probably never be defined). This holds for both the ClientHello message, and the record headers. The protocol version impacts the encoding of records, but the first records are in cleartext (no cryptography), and for them the version can be ignored because cleartext is cleartext (SSL 3.0, TLS 1.0, TLS 1.1 and TLS 1.2 cleartext records differ only by the version specified in the header, but are otherwise identical).

In practice, there are reports of widely deployed implementations which do not tolerate "version" fields where the first byte is not 0x03. There even are implementations which do not support a ClientHello which specifies a version higher than 0x0301 (aka TLS 1.0).

To minimize issues, a client:

  • shall use SSL 3.0 in the records for the ClientHello;
  • should specify its highest supported version in the ClientHello;
  • may fallback, on failure, to trying the ClientHello again, this time claiming a lower maximum supported version (to accomodate old servers which get a stroke when they see "TLS 1.1" or "TLS 1.2").
  • Thanks for that. It was the version mismatch that confused me and I didn't know if I had somehow generated an invalid trace. The interoperability rationale you gave here makes perfect sense.
    – Burhan Ali
    Commented Mar 20, 2013 at 11:57
  • 0xA7C0="167.192"
    – automaton
    Commented Jun 4, 2016 at 1:14
  • Earlier MS SQL Server versions (like 11.00.5343 and 12.00.2269) are example of such a broken implementation. When a JDBC client sends ClientHello, TLSv1.2 during handshake, the server is likely to close the connection in 5-10% cases. See this question for more details. As a workaround, one needs to force the clients into TLSv1 mode.
    – Bass
    Commented Oct 31, 2016 at 18:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .