In public key encryption, a public key algorithm is used to encrypt
data in such a way that it can be decrypted only with the matching
private key. A public-key-encrypted element is encoded as an opaque
vector <0..2^16-1>, where the length is specified by the signing
algorithm and key.
An RSA-encrypted value is encoded with PKCS #1 block type 2, as
described in [PKCS1A].
In the following example,
stream-ciphered struct {
uint8 field1;
uint8 field2;
digitally-signed opaque hash[20];
} UserType;
the contents of hash are used as input for the signing algorithm, and
then the entire structure is encrypted with a stream cipher. The
length of this structure, in bytes, would be equal to two bytes for
field1 and field2, plus two bytes for the length of the signature,
plus the length of the output of the signing algorithm. This is
known because the algorithm and key used for the signing are known
prior to encoding or decoding this structure.
4.8. Constants
Typed constants can be defined for purposes of specification by
declaring a symbol of the desired type and assigning values to it.
Under-specified types (opaque, variable length vectors, and
structures that contain opaque) cannot be assigned values. No fields
of a multi-element structure or vector may be elided.
For example:
struct {
uint8 f1;
uint8 f2;
} Example1;
Example1 ex1 = {1, 4}; /* assigns f1 = 1, f2 = 4 */
5. HMAC and the Pseudorandom Function
A number of operations in the TLS record and handshake layer require
a keyed MAC; this is a secure digest of some data protected by a
secret. Forging the MAC is infeasible without knowledge of the MAC
secret. The construction we use for this operation is known as HMAC,
and is described in [HMAC].
HMAC can be used with a variety of different hash algorithms. TLS
uses it in the handshake with two different algorithms, MD5 and SHA-
1, denoting these as HMAC_MD5(secret, data) and HMAC_SHA(secret,
data). Additional hash algorithms can be defined by cipher suites
and used to protect record data, but MD5 and SHA-1 are hard coded
into the description of the handshaking for this version of the
protocol.
In addition, a construction is required to do expansion of secrets
into blocks of data for the purposes of key generation or validation.
This pseudo-random function (PRF) takes as input a secret, a seed,
and an identifying label and produces an output of arbitrary length.
In order to make the PRF as secure as possible, it uses two hash
algorithms in a way that should guarantee its security if either
algorithm remains secure.
First, we define a data expansion function, P_hash(secret, data) that
uses a single hash function to expand a secret and seed into an
arbitrary quantity of output:
P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
HMAC_hash(secret, A(2) + seed) +
HMAC_hash(secret, A(3) + seed) + ...
Where + indicates concatenation.
A() is defined as:
A(0) = seed
A(i) = HMAC_hash(secret, A(i-1))
P_hash can be iterated as many times as is necessary to produce the
required quantity of data. For example, if P_SHA-1 is being used to
create 64 bytes of data, it will have to be iterated 4 times (through
A(4)), creating 80 bytes of output data; the last 16 bytes of the
final iteration will then be discarded, leaving 64 bytes of output
data.
TLS’s PRF is created by splitting the secret into two halves and
using one half to generate data with P_MD5 and the other half to
generate data with P_SHA-1, then exclusive-ORing the outputs of these
two expansion functions together.
S1 and S2 are the two halves of the secret, and each is the same
length. S1 is taken from the first half of the secret, S2 from the
second half. Their length is created by rounding up the length of
the overall secret, divided by two; thus, if the original secret is
an odd number of bytes long, the last byte of S1 will be the same as
the first byte of S2.
L_S = length in bytes of secret;
L_S1 = L_S2 = ceil(L_S / 2);
The secret is partitioned into two halves (with the possibility of
one shared byte) as described above, S1 taking the first L_S1 bytes,
and S2 the last L_S2 bytes.
The PRF is then defined as the result of mixing the two pseudorandom
streams by exclusive-ORing them together.
PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR
P_SHA-1(S2, label + seed);
The label is an ASCII string. It should be included in the exact
form it is given without a length byte or trailing null character.
For example, the label "slithy toves" would be processed by hashing
the following bytes:
73 6C 69 74 68 79 20 74 6F 76 65 73
Note that because MD5 produces 16-byte outputs and SHA-1 produces
20-byte outputs, the boundaries of their internal iterations will not
be aligned. Generating an 80-byte output will require that P_MD5
iterate through A(5), while P_SHA-1 will only iterate through A(4).
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, reassembled, and 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.1). All such
values must be defined by RFC 2434 Standards Action. See Section 11
for IANA Considerations for ContentType values.
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 taken 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, and encryption
algorithm, and a MAC algorithm. In addition, the parameters for
these algorithms are known: the MAC secret and the bulk encryption
keys 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 Change Cipher Spec 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 that 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, and the block size
of the cipher (if appropriate).
MAC algorithm
An algorithm to be used for message authentication. This
specification includes the size of the hash returned by the MAC
algorithm.
compression algorithm
An algorithm to be used for data compression. This specification
must include all information the algorithm requires 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, idea, aes }
BulkCipherAlgorithm;
enum { stream, block } CipherType;
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;
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 four items:
client write MAC secret
server write MAC secret
client write key
server write key
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. For stream ciphers,
this will also contain whatever state information is necessary 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. Sequence numbers do not wrap. If a TLS
implementation would need to wrap a sequence number, it must
renegotiate instead. A sequence number is incremented after each
record: specifically, the first record transmitted under a
particular connection state MUST 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;
type
The higher-level protocol used to process the enclosed fragment.
version
The version of the protocol being employed. This document
describes TLS Version 1.1, which uses the version { 3, 2 }. The
version value 3.2 is historical: TLS version 1.1 is a minor
modification to the TLS 1.0 protocol, which was itself a minor
modification to the SSL 3.0 protocol, which bears the version
value 3.0. (See Appendix A.1.)
length
The length (in bytes) of the following TLSPlaintext.fragment. The
length should not exceed 2^14.
fragment
The application data. This data is transparent and is 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. However, records MUST be
delivered to the network in the same order as they are protected by
the record layer. Recipients MUST receive and process interleaved
application layer traffic during handshakes subsequent to the first
one on a connection.
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;
length
The length (in bytes) of the following TLSCompressed.fragment.
The length should not exceed 2^14 + 1024.
fragment
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;
type
The type field is identical to TLSCompressed.type.
version
The version field is identical to TLSCompressed.version.
length
The length (in bytes) of the following TLSCiphertext.fragment.
The length may not exceed 2^14 + 2048.
fragment
The encrypted form of TLSCompressed.fragment, with the MAC.
6.2.3.1. 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.
seq_num
The sequence number for this record.
hash
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.
6.2.3.2. CBC Block Cipher
For block ciphers (such as RC2, DES, or AES), the encryption and MAC
functions convert TLSCompressed.fragment structures to and from block
TLSCiphertext.fragment structures.
block-ciphered struct {
opaque IV[CipherSpec.block_length];
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 6.2.3.1.
IV
Unlike previous versions of SSL and TLS, TLS 1.1 uses an explicit
IV in order to prevent the attacks described by [CBCATT]. We
recommend the following equivalently strong procedures. For
clarity we use the following notation.
IV
The transmitted value of the IV field in the GenericBlockCipher
structure.
CBC residue
The last ciphertext block of the previous record.
mask
The actual value that the cipher XORs with the plaintext prior
to encryption of the first cipher block of the record.
In prior versions of TLS, there was no IV field and the CBC
residue and mask were one and the same. See Sections 6.1,
6.2.3.2, and 6.3, of [TLS1.0] for details of TLS 1.0 IV handling.
One of the following two algorithms SHOULD be used to generate the
per-record IV:
(1) Generate a cryptographically strong random string R of length
CipherSpec.block_length. Place R in the IV field. Set the
mask to R. Thus, the first cipher block will be encrypted as
E(R XOR Data).
(2) Generate a cryptographically strong random number R of length
CipherSpec.block_length and prepend it to the plaintext prior
to encryption. In this case either:
(a) The cipher may use a fixed mask such as zero.
(b) The CBC residue from the previous record may be used as
the mask. This preserves maximum code compatibility with
TLS 1.0 and SSL 3. It also has the advantage that it does
not require the ability to quickly reset the IV, which is
known to be a problem on some systems.
In either (2)(a) or (2)(b) the data (R || data) is fed into
the encryption process. The first cipher block (containing
E(mask XOR R) is placed in the IV field. The first block of
content contains E(IV XOR data).
The following alternative procedure MAY be used; however, it has
not been demonstrated to be as cryptographically strong as the
above procedures. The sender prepends a fixed block F to the
plaintext (or, alternatively, a block generated with a weak PRNG).
He then encrypts as in (2), above, using the CBC residue from the
previous block as the mask for the prepended block. Note that in
this case the mask for the first record transmitted by the
application (the Finished) MUST be generated using a
cryptographically strong PRNG.
The decryption operation for all three alternatives is the same.
The receiver decrypts the entire GenericBlockCipher structure and
then discards the first cipher block, corresponding to the IV
component.
padding
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, 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 that are 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 receiver
MUST check this padding and SHOULD use the bad_record_mac alert to
indicate padding errors.
padding_length
The padding length MUST 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 CipherSpec.block_length, 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, then the length before padding is 82 bytes (this does
not include the IV, which may or may not be encrypted, as
discussed above). Thus, the padding length modulo 8 must be
equal to 6 in order to make the total length an even