Overview#SSL-TLS is layered and the bottom layer is the Record Protocol.
Record Protocol takes messages to be transmitted, fragments the data into manageable blocks, protects the records, and transmits the result. Received data is verified and decrypted, reassembled, and then delivered to higher-level clients.
TLS records are typed, which allows multiple higher-level protocols to be multiplexed over the same record layer. TLS 1.3 specifies three content types: handshake, application data, and alert. Implementations MUST NOT send record types not defined in this document unless negotiated by some extension. If a TLS implementation receives an unexpected record type, it MUST terminate the connection with an "unexpected_message" alert. New record content type values are assigned by IANA in the TLS ContentType Registry as described in TLS 1.3 Section 10.
Record Layer#The record layer fragments information blocks into TLSPlaintext records carrying data in chunks of 2^14 bytes or less. Message boundaries are handled differently depending on the underlying ContentType. Any future content types MUST specify appropriate rules. Note that these rules are stricter than what was enforced in TLS 1.2.
- TLS Handshake Message MUST NOT be interleaved with other record types. That is, if a TLS Handshake Message is split over two or more records, there MUST NOT be any other records between them.
- TLS Handshake Message MUST NOT span key changes. Implementations MUST verify that all messages immediately preceding a key change align with a record boundary; if not, then they MUST terminate the connection with an "unexpected_message" alert. Because the ClientHello, EndOfEarlyData, ServerHello, TLS-Finished, and KeyUpdate messages can immediately precede a key change, implementations MUST send these messages in alignment with a record boundary.
TLS Alert Messages (Section 6) MUST NOT be fragmented across records and multiple TLS Alert Messages MUST NOT be coalesced into a single TLSPlaintext record. In other words, a record with an Alert type MUST contain exactly one message.
application_data are always protected. Zero-lengthfragments of Application Data MAY be sent as they are potentially useful as a traffic analysis countermeasure.SSL-TLS tunnel is split into records (or blocks). Over the wire (the underlying TCP socket or TCP-like medium), a record looks like this:
HH V1:V2 L1:L2 datawhere:
- HH is a single byte which indicates the TLS ContentType which indicates the data type in the record.
- V1:V2 is the protocol version, over two bytes. For all versions currently defined,
- L1:L2 is the length of data, in bytes (Big-Endian convention is used: the length is 256*L1+L2). The total length of data cannot exceed 18432 bytes, but in practice it cannot even reach that value.
- five-byte header (HH V1:V2)
- followed by at most 18 kB of data. (L1:L2)
The data is where Symmetric Key encryption and integrity checks are applied. When a record is emitted, both sender and receiver are supposed to agree on which Cryptographic algorithms are currently applied, and with which keys. The agreement is obtained through the TLS Handshake protocol. TLS Compression, if any, is also applied at that point.
In full details, the building of a record works like this:
- Initially, there are some bytes to transfer; these are application_data or some other kind of bytes. This payload consists of at most 16,384 bytes, but possibly less (a payload of length 0 is legal, but it turns out that Internet Explorer 6.0 does not like that at all).
- The application_data is then compressed with whatever TLS Compression algorithm is currently agreed upon. TLS Compression is stateful, and thus may depend upon the contents of previous records. In practice, TLS Compression is either "null" (no compression at all) or "Deflate" RFC 3749, the latter being currently courteously but firmly shown the exit door in the Web context, due to the recent CRIME attack. TLS Compression aims at shortening data, but it must necessarily expand it slightly in some unfavorable situations (due to the pigeonhole principle). SSL allows for an expansion of at most 1024 bytes. Of course, null TLS Compression never expands (but never shortens either); Deflate will expand by at most 10 bytes, if the implementation is any good.
- The compressed application_data is then protected against alterations and encrypted. If the current encryption-and-integrity algorithms are "null", then this step is a no-operation. Otherwise, a Message Authentication Code is appended, then some padding (depending on the encryption algorithm), and the result is encrypted. These steps again induce some expansion, which the SSL standard limits to 1024 extra bytes (combined with the maximum expansion from the compression step, this brings us to the 18432 bytes, to which we must add the 5-byte header).
The Message Authentication Code is, usually, HMAC with one of the usual Cryptographic Hash Functions (with SSLv3, this is not the "true" HMAC but something very similar and, to the best of our knowledge, as secure as HMAC). Encryption will use either a Block Cipher in CBC mode, or the RC4 Stream Cipher.
Note that, in theory, other kinds of modes or algorithms could be employed, for instance one of these nifty modes which combine encryption and integrity checks; there are even some RFC for that. In practice, though, deployed implementations do not know of these yet, so they do HMAC and CBC. Crucially, the Message Authentication Code is first computed and appended to the application_data, and the result is encrypted. This is MAC-then-encrypt and it is actually not a very good idea. The Message Authentication Code is computed over the concatenation of the (compressed) payload and a sequence number, so that an industrious attacker may not swap records.