Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Application Data Records in the TLSv1.3 Handshake? #17654

Closed
mspncp opened this issue Feb 7, 2022 · 9 comments
Closed

Application Data Records in the TLSv1.3 Handshake? #17654

mspncp opened this issue Feb 7, 2022 · 9 comments
Labels
resolved: answered The issue contained a question which has been answered triaged: question The issue contains a question

Comments

@mspncp
Copy link
Contributor

mspncp commented Feb 7, 2022

Some days ago a colleague confronted me with an interesting TLS problem: After switching the libssl library from 1.0.2 to 1.1.1 he encountered the issue that immediately after the SSL_connect() his previously working code now blocked in an SSL_read_ex() call, even though a preceding select() call had just returned marking the socket as readable. After some research, I found out that part of the problem was that the SSL_MODE_AUTO_RETRY mode is enabled by default since 1.1.1, which hadn't been the case previously. Disabling the mode and handling the SSL_ERROR_WANT_READ errors correctly fixed his problem.

What astonished me during my investigations was the fact the problem occurred only with the TLSv1.3 protocol and that the blocking was caused by TLS Records marked as 'Application Data' which were transmitted as part of the initial handshake. (The TLSv1.2 exchange contains only 'Handshake' and 'Change Cipher Spec' records.) Those 'Application Data' records seem to play a special role, as they are generated and consumed by the libssl library and are not handed to the application. Can anybody of you tell me what those records contain and why they are marked as 'Application Data' even though they are not intended for the application? I know that the RFC allows optional application data during the handshake, but I couldn't find any specific information about the possible use cases.

Regards, and thanks in advance,

Matthias

Below you find an outline of a simple Handshake (a little C client calling SSL_connect() against an openssl s_server, both running on localhost), recorded with tshark, the little command line brother of wireshark. (The full transcript is contained in the attached files tls13-connect.txt resp. tls12-connect.txt, see links below.)

TLSv1.3 Handshake

grep -e 'Transport Layer Security' -e 'TLS.*Layer:' -A 4 tls13-connect.txt

Transport Layer Security
    TLSv1 Record Layer: Handshake Protocol: Client Hello
        Content Type: Handshake (22)
        Version: TLS 1.0 (0x0301)
        Length: 288
        Handshake Protocol: Client Hello
--
Transport Layer Security
    TLSv1.2 Record Layer: Handshake Protocol: Server Hello
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 122
        Handshake Protocol: Server Hello
--
    TLSv1.3 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec
        Content Type: Change Cipher Spec (20)
        Version: TLS 1.2 (0x0303)
        Length: 1
        Change Cipher Spec Message
    TLSv1.3 Record Layer: Application Data Protocol: Application Data
        Opaque Type: Application Data (23)
        Version: TLS 1.2 (0x0303)
        Length: 23
        Encrypted Application Data: 70f288f41acbbd8f8a1790896a78f7f3780199829b3e7d
    TLSv1.3 Record Layer: Application Data Protocol: Application Data
        Opaque Type: Application Data (23)
        Version: TLS 1.2 (0x0303)
        Length: 643
        Encrypted Application Data: 03540631042cfc1884b3848a6482648dded2585460901546ac4ebce7b96ebb43f5228eea…
    TLSv1.3 Record Layer: Application Data Protocol: Application Data
        Opaque Type: Application Data (23)
        Version: TLS 1.2 (0x0303)
        Length: 97
        Encrypted Application Data: ac0e7ecafb2c3fa1f34a84eb6fdb8bd256486e229df23f436db1f4b6b4e46b84df845ffc…
    TLSv1.3 Record Layer: Application Data Protocol: Application Data
        Opaque Type: Application Data (23)
        Version: TLS 1.2 (0x0303)
        Length: 69
        Encrypted Application Data: 8e1199e00245e2a8db2502ff10de8c9d72ad20d1427c290a827b3ab12a62ef8deb6b4af5…
--
Transport Layer Security
    TLSv1.3 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec
        Content Type: Change Cipher Spec (20)
        Version: TLS 1.2 (0x0303)
        Length: 1
        Change Cipher Spec Message
    TLSv1.3 Record Layer: Application Data Protocol: Application Data
        Opaque Type: Application Data (23)
        Version: TLS 1.2 (0x0303)
        Length: 69
        Encrypted Application Data: 1d5d5aa3ac0563fc5a3746e86e8dc5de2904eef5c60c05ab09883c4e2f55f008ab68ff66…
--
Transport Layer Security
    TLSv1.3 Record Layer: Application Data Protocol: Application Data
        Opaque Type: Application Data (23)
        Version: TLS 1.2 (0x0303)
        Length: 234
        Encrypted Application Data: c524a025ab55c3f673c6cfe2a34f3f1e21086643941b5855b3ae48cf4194ebff6b15c517…
--
Transport Layer Security
    TLSv1.3 Record Layer: Application Data Protocol: Application Data
        Opaque Type: Application Data (23)
        Version: TLS 1.2 (0x0303)
        Length: 234
        Encrypted Application Data: cd84b937f49ee3e0943462ddd12963bf8b0c6a3bc342d11c9820b858212a786520ef9941…

TLSv1.2 Handshake (SSL_connect() against 'openssl s_server')

grep -e 'Transport Layer Security' -e 'TLS.*Layer:' -A 4 tls12-connect.txt

Transport Layer Security
    TLSv1 Record Layer: Handshake Protocol: Client Hello
        Content Type: Handshake (22)
        Version: TLS 1.0 (0x0301)
        Length: 189
        Handshake Protocol: Client Hello
--
Transport Layer Security
    TLSv1.2 Record Layer: Handshake Protocol: Server Hello
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 65
        Handshake Protocol: Server Hello
--
    TLSv1.2 Record Layer: Handshake Protocol: Certificate
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 623
        Handshake Protocol: Certificate
--
    TLSv1.2 Record Layer: Handshake Protocol: Server Key Exchange
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 115
        Handshake Protocol: Server Key Exchange
--
    TLSv1.2 Record Layer: Handshake Protocol: Server Hello Done
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 4
        Handshake Protocol: Server Hello Done
--
Transport Layer Security
    TLSv1.2 Record Layer: Handshake Protocol: Client Key Exchange
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 37
        Handshake Protocol: Client Key Exchange
--
    TLSv1.2 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec
        Content Type: Change Cipher Spec (20)
        Version: TLS 1.2 (0x0303)
        Length: 1
        Change Cipher Spec Message
    TLSv1.2 Record Layer: Handshake Protocol: Encrypted Handshake Message
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 40
        Handshake Protocol: Encrypted Handshake Message
--
Transport Layer Security
    TLSv1.2 Record Layer: Handshake Protocol: New Session Ticket
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 170
        Handshake Protocol: New Session Ticket
--
    TLSv1.2 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec
        Content Type: Change Cipher Spec (20)
        Version: TLS 1.2 (0x0303)
        Length: 1
        Change Cipher Spec Message
    TLSv1.2 Record Layer: Handshake Protocol: Encrypted Handshake Message
        Content Type: Handshake (22)
        Version: TLS 1.2 (0x0303)
        Length: 40
        Handshake Protocol: Encrypted Handshake Message
@mspncp mspncp added the issue: question The issue was opened to ask a question label Feb 7, 2022
@kaduk
Copy link
Contributor

kaduk commented Feb 7, 2022

TLS 1.3 encrypts most of the handshake, see https://datatracker.ietf.org/doc/html/rfc8446#page-11 with the legend that {} and [] both indicate encrypted messages, just encrypted with a different key.
Encrypted records are given the outer content type of "Application Data", with the actual content type being encrypted.
https://datatracker.ietf.org/doc/html/rfc8446#section-5.2 has some more details of this process.

@mattcaswell
Copy link
Member

Its a TLSv1.3 protocol thing. Records now have an "outer" and an "inner" content type. As soon as records start getting encrypted (which is early in TLSv1.3) the "outer" content type gets set to "Application Data". The "inner" content type tells you the real content type of the record - but this is encrypted and not visible to a passive observer.

@mspncp
Copy link
Contributor Author

mspncp commented Feb 7, 2022

Thanks for the quick reply @kaduk and @mattcaswell! Now things make more sense to me. Just for curiousity: was the "Application Data" type chosen deliberately to prevent stupid middleboxes from tampering with the content?

@davidben
Copy link
Contributor

davidben commented Feb 7, 2022

A new content type would almost certainly break middleboxes, though I don't know if we explicitly tried it. We even played with a smaller, two-byte header (version and content type are a waste of bytes), but that one we experimentally confirmed breaks middleboxes. That leaves always using application_data (making the handshake confusing) or always using handshake (making application data confusing). TLS 1.3 went with the former. Dunno whether handshake would also have gotten through middleboxes, but it's mostly an arbitrary choice.

@mspncp
Copy link
Contributor Author

mspncp commented Feb 7, 2022

Thank you all for your enlightening replies!

@mspncp mspncp closed this as completed Feb 7, 2022
@mspncp mspncp added resolved: answered The issue contained a question which has been answered triaged: question The issue contains a question and removed issue: question The issue was opened to ask a question labels Feb 7, 2022
@mspncp
Copy link
Contributor Author

mspncp commented Feb 9, 2022

Just for curiousity: was the "Application Data" type chosen deliberately to prevent stupid middleboxes from tampering with the content?

Postscript: indeed, the RFC explicitly states on page 81 that the record type was chosen for compatibility reasons with middleboxes:

opaque_type:  The outer opaque_type field of a TLSCiphertext record
      is always set to the value 23 (application_data) for outward
      compatibility with middleboxes accustomed to parsing previous
      versions of TLS.  The actual content type of the record is found
      in TLSInnerPlaintext.type after decryption.

@cangSDARM
Copy link

Why does TLS1.3's 0x17 Application Data also need an Outer wrapper? Application Data is already an "Application Data" and should not require a TLS1.2 Outer wrapper.

Sorry to ask that in this Issue. I didn't find the relevant question online, only this Issue has enough context :)

@mattcaswell
Copy link
Member

Why does TLS1.3's 0x17 Application Data also need an Outer wrapper? Application Data is already an "Application Data" and should not require a TLS1.2 Outer wrapper.

TLSv1.3 can send alerts, handshake messages or application data all with the same application data outer content type. You need an inner content type to determine which one it really is, even for application data.

@davidben
Copy link
Contributor

davidben commented Jun 6, 2023

The outer content type is a compatibility hack were stuck with, sadly. Most of the header in an encrypted TLS 1.3 record is vestigial. Folks considered a short record type during TLS 1.3's development, but it broke too much network middleware, which would try to parse the record headers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
resolved: answered The issue contained a question which has been answered triaged: question The issue contains a question
Projects
None yet
Development

No branches or pull requests

5 participants