Subject: [TLS] Inconsistent TLSCiphertext definition

From: Yishuai Li <[email-masked]>
Date: Thu, 27 Jun 2019 17:40:19 -0400

Dear TLS working group,

RFC 8446 Section 4 Page 23 says:

> Handshake messages are supplied to the TLS record layer, where they are
> encapsulated within one or more TLSPlaintext or TLSCiphertext structures which
> are processed and transmitted as specified by the current active connection
> state.

RFC 8448 Section 3 Page 8 sends a handshake record, with content type
application_data (0x17). Should I read it as: "The handshake record is
encapsulated within a TLSCiphertext"?

1. If yes, RFC 8446 Section 5.2 Page 80 says:

    > encrypted_record: The AEAD-encrypted form of the serialized
    > TLSInnerPlaintext structure.

    However, the payload does not follow the structure of TLSInnerPlaintext (RFC
    8446 Section 5.2 Page 79), but that of Handshake (RFC 8446 Section 4 Page
    24) instead.

2. If no, which section of RFC8446 specifies the complete record?

Thanks,
Yishuai Li

---

From: Ilari Liusvaara <[email-masked]>
Date: Fri, 28 Jun 2019 11:00:55 +0300

> 2. If no, which section of RFC8446 specifies the complete record?

The payload shown is TLSInnerPlaintext.content. It gets processed as
follows:

1) 0x16 byte is appended to plaintext to yield TLSInnerPlaintext
   (since this is encrypted handshake message), together with 0
   trailing zeroes (for padding, there could be more).
2) The TLSInnerPlaintext is AEAD-encrypted
3) The record header is prepended (with application_data type, since it
   is encrypted).

Note that the size difference between payload and record is 22 bytes:

- 5 bytes for the record header (0x17 0x03 0x03 0x02 0xa2).
- 1 byte for the encrypted record type (whatever 0x16 encrypts to)
- 0 bytes for padding
- 16 bytes for the AES-GCM tag.

Exactly matching the amount expected.

-Ilari

---

From: Yishuai Li <[email-masked]>
Date: Sat, 29 Jun 2019 08:36:49 -0400

Thanks Ilari.

>    trailing zeroes (for padding, there could be more).

1. Is it worth adding this explanation to RFC 8448? Neither
"TLSInnerPlaintext" or "0x16" was mentioned in the context, making
this "Informational" RFC not so informative.

2. Is there a specific reason to structure TLSInnerPlaintext this way?
Does it make parsing counterintuitive that the parser must know
ContentType before locating ContentType?

-Yishuai

---

From: Ilari Liusvaara <[email-masked]>
Date: Sat, 29 Jun 2019 17:41:24 +0300

> this "Informational" RFC not so informative.

Well, the RFC 8448 does not cosider how the record protection
works internally.
 
> ContentType before locating ContentType?

Yes, to encrypt the content type of encrypted records and offer to
pad them with no extra overhead (there is no padding length field).
It was not possible to encrypt the main content type field due to
the fact that the range is not bit-aligned.

Parsing should not be that difficult:

- If outer content type is 21, it is unencrypted alert, if 22 it is
  unencrypted handshake fragment and if 23, it is encrypted record,
  that one should attempt to decrypt. If this fails, send fatal
  alert.
- For unencrypted records, payload starts at byte 5 of the record
  and extends to the end.
- For encrypted records, After decrypting, scan for last nonzero
  byte. If none is found, send fatal alert.
- The last nonzero byte is true content type.
- The part of decrypt output before that last nonzero byte is the
  record payload.

-Ilari