5<- index ->7

6. The TLS Record Protocol

The TLS Record Protocol is a layered protocol. At each layer, messages may include fields for length, description, and content. The Record Protocol takes messages to be transmitted, fragments the data into manageable blocks, optionally compresses the data, applies a MAC, encrypts, and transmits the result. Received data is decrypted, verified, decompressed, and reassembled, then delivered to higher level clients.

Four record protocol clients are described in this document: the handshake protocol, the alert protocol, the change cipher spec protocol, and the application data protocol. In order to allow extension of the TLS protocol, additional record types can be supported by the record protocol. Any new record types should allocate type values immediately beyond the ContentType values for the four record types described here (see Appendix A.2). If a TLS implementation receives a record type it does not understand, it should just ignore it. Any protocol designed for use over TLS must be carefully designed to deal with all possible attacks against it. Note that because the type and length of a record are not protected by encryption, care should be take to minimize the value of traffic analysis of these values.

6.1. Connection states

A TLS connection state is the operating environment of the TLS Record Protocol. It specifies a compression algorithm, encryption algorithm, and MAC algorithm. In addition, the parameters for these algorithms are known: the MAC secret and the bulk encryption keys and IVs for the connection in both the read and the write directions. Logically, there are always four connection states outstanding: the current read and write states, and the pending read and write states. All records are processed under the current read and write states. The security parameters for the pending states can be set by the TLS Handshake Protocol, and the Handshake Protocol can selectively make either of the pending states current, in which case the appropriate current state is disposed of and replaced with the pending state; the pending state is then reinitialized to an empty state. It is illegal to make a state which has not been initialized with security parameters a current state. The initial current state always specifies that no encryption, compression, or MAC will be used.

The security parameters for a TLS Connection read and write state are set by providing the following values:

connection end
Whether this entity is considered the "client" or the "server" in this connection.
bulk encryption algorithm
An algorithm to be used for bulk encryption. This specification includes the key size of this algorithm, how much of that key is secret, whether it is a block or stream cipher, the block size of the cipher (if appropriate), and whether it is considered an "export" cipher.
MAC algorithm
An algorithm to be used for message authentication. This specification includes the size of the hash which is returned by the MAC algorithm.
compression algorithm
An algorithm to be used for data compression. This specification must include all information the algorithm requires to do compression.
master secret
A 48 byte secret shared between the two peers in the connection.
client random
A 32 byte value provided by the client.
server random
A 32 byte value provided by the server.

These parameters are defined in the presentation language as:

enum { server, client } ConnectionEnd;

enum { null, rc4, rc2, des, 3des, des40 } BulkCipherAlgorithm;

enum { stream, block } CipherType;

enum { true, false } IsExportable;

enum { null, md5, sha } MACAlgorithm;

enum { null(0), (255) } CompressionMethod;

/* The algorithms specified in CompressionMethod, BulkCipherAlgorithm, and MACAlgorithm may be added to. */

       struct {
           ConnectionEnd          entity;
           BulkCipherAlgorithm    bulk_cipher_algorithm;
           CipherType             cipher_type;
           uint8                  key_size;
           uint8                  key_material_length;
           IsExportable           is_exportable;
           MACAlgorithm           mac_algorithm;
           uint8                  hash_size;
           CompressionMethod      compression_algorithm;
           opaque                 master_secret[48];
           opaque                 client_random[32];
           opaque                 server_random[32];
       } SecurityParameters;

The record layer will use the security parameters to generate the following six items:

client write MAC secret
server write MAC secret
client write key
server write key
client write IV (for block ciphers only)
server write IV (for block ciphers only)

The client write parameters are used by the server when receiving and processing records and vice-versa. The algorithm used for generating these items from the security parameters is described in section 6.3.

Once the security parameters have been set and the keys have been generated, the connection states can be instantiated by making them the current states. These current states must be updated for each record processed. Each connection state includes the following elements:

compression state
The current state of the compression algorithm.
cipher state
The current state of the encryption algorithm. This will consist of the scheduled key for that connection. In addition, for block ciphers running in CBC mode (the only mode specified for TLS), this will initially contain the IV for that connection state and be updated to contain the ciphertext of the last block encrypted or decrypted as records are processed. For stream ciphers, this will contain whatever the necessary state information is to allow the stream to continue to encrypt or decrypt data.
MAC secret
The MAC secret for this connection as generated above.
sequence number
Each connection state contains a sequence number, which is maintained separately for read and write states. The sequence number must be set to zero whenever a connection state is made the active state. Sequence numbers are of type uint64 and may not exceed 2^64-1. A sequence number is incremented after each record: specifically, the first record which is transmitted under a particular connection state should use sequence number 0.

6.2. Record layer

The TLS Record Layer receives uninterpreted data from higher layers in non-empty blocks of arbitrary size.

6.2.1. Fragmentation

The record layer fragments information blocks into TLSPlaintext records carrying data in chunks of 2^14 bytes or less. Client message boundaries are not preserved in the record layer (i.e., multiple client messages of the same ContentType may be coalesced into a single TLSPlaintext record, or a single message may be fragmented across several records).

struct {

uint8 major, minor;

} ProtocolVersion;

enum {

change_cipher_spec(20), alert(21), handshake(22), application_data(23), (255)

} ContentType;

struct {

ContentType type; ProtocolVersion version; uint16 length; opaque fragment[TLSPlaintext.length];

} TLSPlaintext;

The higher level protocol used to process the enclosed fragment.
The version of the protocol being employed. This document describes TLS Version 1.0, which uses the version { 3, 1 }. The version value 3.1 is historical: TLS version 1.0 is a minor modification to the SSL 3.0 protocol, which bears the version value 3.0. (See Appendix A.1).
The length (in bytes) of the following TLSPlaintext.fragment. The length should not exceed 2^14.
The application data. This data is transparent and treated as an independent block to be dealt with by the higher level protocol specified by the type field.
Note: Data of different TLS Record layer content types may be interleaved. Application data is generally of lower precedence for transmission than other content types.

6.2.2. Record compression and decompression

All records are compressed using the compression algorithm defined in the current session state. There is always an active compression algorithm; however, initially it is defined as CompressionMethod.null. The compression algorithm translates a TLSPlaintext structure into a TLSCompressed structure. Compression functions are initialized with default state information whenever a connection state is made active.

Compression must be lossless and may not increase the content length by more than 1024 bytes. If the decompression function encounters a TLSCompressed.fragment that would decompress to a length in excess of 2^14 bytes, it should report a fatal decompression failure error.

struct {

ContentType type; /* same as TLSPlaintext.type */
ProtocolVersion version;/* same as TLSPlaintext.version */
uint16 length; opaque fragment[TLSCompressed.length];

} TLSCompressed;

The length (in bytes) of the following TLSCompressed.fragment. The length should not exceed 2^14 + 1024.
The compressed form of TLSPlaintext.fragment.

Note: A CompressionMethod.null operation is an identity operation; no fields are altered.

Implementation note:
Decompression functions are responsible for ensuring that messages cannot cause internal buffer overflows.

6.2.3. Record payload protection

The encryption and MAC functions translate a TLSCompressed structure into a TLSCiphertext. The decryption functions reverse the process. The MAC of the record also includes a sequence number so that missing, extra or repeated messages are detectable.

       struct {
           ContentType type;
           ProtocolVersion version;
           uint16 length;
           select (CipherSpec.cipher_type) {
               case stream: GenericStreamCipher;
               case block: GenericBlockCipher;
           } fragment;
       } TLSCiphertext;

The type field is identical to TLSCompressed.type.
The version field is identical to TLSCompressed.version.
The length (in bytes) of the following TLSCiphertext.fragment. The length may not exceed 2^14 + 2048.
The encrypted form of TLSCompressed.fragment, with the MAC. Null or standard stream cipher

Stream ciphers (including BulkCipherAlgorithm.null - see Appendix A.6) convert TLSCompressed.fragment structures to and from stream TLSCiphertext.fragment structures.

stream-ciphered struct {

opaque content[TLSCompressed.length];
opaque MAC[CipherSpec.hash_size];

} GenericStreamCipher;

The MAC is generated as:

HMAC_hash(MAC_write_secret, seq_num + TLSCompressed.type + TLSCompressed.version + TLSCompressed.length + TLSCompressed.fragment));

where "+" denotes concatenation.

The sequence number for this record.
The hashing algorithm specified by SecurityParameters.mac_algorithm.

Note that the MAC is computed before encryption. The stream cipher encrypts the entire block, including the MAC. For stream ciphers that do not use a synchronization vector (such as RC4), the stream cipher state from the end of one record is simply used on the subsequent packet. If the CipherSuite is TLS_NULL_WITH_NULL_NULL, encryption consists of the identity operation (i.e., the data is not encrypted and the MAC size is zero implying that no MAC is used). TLSCiphertext.length is TLSCompressed.length plus CipherSpec.hash_size. CBC block cipher

For block ciphers (such as RC2 or DES), the encryption and MAC functions convert TLSCompressed.fragment structures to and from block TLSCiphertext.fragment structures.

block-ciphered struct {

opaque content[TLSCompressed.length];
opaque MAC[CipherSpec.hash_size];
uint8 padding[GenericBlockCipher.padding_length];
uint8 padding_length;

 } GenericBlockCipher;

The MAC is generated as described in Section

Padding that is added to force the length of the plaintext to be an integral multiple of the block cipher's block length. The padding may be any length up to 255 bytes long, as long as it results in the TLSCiphertext.length being an integral multiple of the block length. Lengths longer than necessary might be desirable to frustrate attacks on a protocol based on analysis of the lengths of exchanged messages. Each uint8 in the padding data vector must be filled with the padding length value.
The padding length should be such that the total size of the GenericBlockCipher structure is a multiple of the cipher's block length. Legal values range from zero to 255, inclusive. This length specifies the length of the padding field exclusive of the padding_length field itself.

The encrypted data length (TLSCiphertext.length) is one more than the sum of TLSCompressed.length, CipherSpec.hash_size, and padding_length.

Example: If the block length is 8 bytes, the content length (TLSCompressed.length) is 61 bytes, and the MAC length is 20 bytes, the length before padding is 82 bytes. Thus, the padding length modulo 8 must be equal to 6 in order to make the total length an even multiple of 8 bytes (the block length). The padding length can be 6, 14, 22, and so on, through 254. If the padding length were the minimum necessary, 6, the padding would be 6 bytes, each containing the value 6. Thus, the last 8 octets of the GenericBlockCipher before block encryption would be xx 06 06 06 06 06 06 06, where xx is the last octet of the MAC.
Note: With block ciphers in CBC mode (Cipher Block Chaining) the initialization vector (IV) for the first record is generated with the other keys and secrets when the security parameters are set. The IV for subsequent records is the last ciphertext block from the previous record.

6.3. Key calculation

The Record Protocol requires an algorithm to generate keys, IVs, and MAC secrets from the security parameters provided by the handshake protocol.

The master secret is hashed into a sequence of secure bytes, which are assigned to the MAC secrets, keys, and non-export IVs required by the current connection state (see Appendix A.6). CipherSpecs require a client write MAC secret, a server write MAC secret, a client write key, a server write key, a client write IV, and a server write IV, which are generated from the master secret in that order. Unused values are empty.

When generating keys and MAC secrets, the master secret is used as an entropy source, and the random values provide unencrypted salt material and IVs for exportable ciphers.

To generate the key material, compute

key_block = PRF(SecurityParameters.master_secret, "key expansion", SecurityParameters.server_random + SecurityParameters.client_random);

until enough output has been generated. Then the key_block is partitioned as follows:


The client_write_IV and server_write_IV are only generated for non- export block ciphers. For exportable block ciphers, the initialization vectors are generated later, as described below. Any extra key_block material is discarded.

Implementation note:
The cipher spec which is defined in this document which requires the most material is 3DES_EDE_CBC_SHA: it requires 2 x 24 byte keys, 2 x 20 byte MAC secrets, and 2 x 8 byte IVs, for a total of 104 bytes of key material.

Exportable encryption algorithms (for which CipherSpec.is_exportable is true) require additional processing as follows to derive their final write keys:

final_client_write_key = PRF(SecurityParameters.client_write_key, "client write key", SecurityParameters.client_random + SecurityParameters.server_random);
final_server_write_key = PRF(SecurityParameters.server_write_key, "server write key", SecurityParameters.client_random + SecurityParameters.server_random);

Exportable encryption algorithms derive their IVs solely from the random values from the hello messages:

iv_block = PRF("", "IV block", SecurityParameters.client_random + SecurityParameters.server_random);

The iv_block is partitioned into two initialization vectors as the key_block was above:


Note that the PRF is used without a secret in this case: this just means that the secret has a length of zero bytes and contributes nothing to the hashing in the PRF.

6.3.1. Export key generation example

TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 requires five random bytes for each of the two encryption keys and 16 bytes for each of the MAC keys, for a total of 42 bytes of key material. The PRF output is stored in the key_block. The key_block is partitioned, and the write keys are salted because this is an exportable encryption algorithm.

key_block = PRF(master_secret, "key expansion", server_random + client_random)[0..41]
client_write_MAC_secret = key_block[0..15]
server_write_MAC_secret = key_block[16..31]
client_write_key = key_block[32..36]
server_write_key = key_block[37..41]

final_client_write_key = PRF(client_write_key, "client write key", client_random + server_random)[0..15]
final_server_write_key = PRF(server_write_key, "server write key", client_random + server_random)[0..15]

iv_block = PRF("", "IV block", client_random + server_random)[0..15]
client_write_IV = iv_block[0..7]
server_write_IV = iv_block[8..15]