Zum Hauptinhalt springen

6. Das TLS-Record-Protokoll (The TLS Record Protocol)

Das TLS-Record-Protokoll (TLS Record Protocol) ist ein geschichtetes Protokoll. Auf jeder Ebene können Nachrichten Felder für Länge, Beschreibung und Inhalt enthalten. Das Record-Protokoll nimmt zu übertragende Nachrichten entgegen, fragmentiert die Daten in handhabbare Blöcke, komprimiert optional die Daten, wendet einen MAC an, verschlüsselt und überträgt dann das Ergebnis. Empfangene Daten werden entschlüsselt, verifiziert, dekomprimiert, wieder zusammengesetzt und dann an Clients höherer Ebene geliefert.

Vier Protokolle, die das Record-Protokoll verwenden, werden in diesem Dokument beschrieben: das Handshake-Protokoll, das Alert-Protokoll, das Change Cipher Spec-Protokoll und das Application Data-Protokoll. Um Erweiterungen des TLS-Protokolls zu ermöglichen, kann das Record-Protokoll zusätzliche Record Content Types unterstützen. Neue Record Content Type-Werte werden von der IANA im TLS Content Type Registry zugewiesen, wie in Abschnitt 12 beschrieben.

Implementierungen DÜRFEN NICHT (MUST NOT) Record-Typen senden, die in diesem Dokument nicht definiert sind, es sei denn, sie werden durch eine Erweiterung ausgehandelt. Wenn eine TLS-Implementierung einen unerwarteten Record-Typ empfängt, MUSS (MUST) sie einen unexpected_message-Alert senden.

Jedes Protokoll, das für die Verwendung über TLS entwickelt wurde, muss sorgfältig entworfen werden, um mit allen möglichen Angriffen dagegen umzugehen. Praktisch bedeutet dies, dass der Protokollentwickler sich bewusst sein muss, welche Sicherheitseigenschaften TLS bietet und nicht bietet, und sich nicht sicher auf letztere verlassen kann.

Beachten Sie insbesondere, dass Typ und Länge eines Records nicht durch Verschlüsselung geschützt sind. Wenn diese Informationen selbst sensibel sind, möchten Anwendungsentwickler möglicherweise Maßnahmen (Padding, Cover-Traffic) ergreifen, um Informationslecks zu minimieren.

6.1. Verbindungszustände (Connection States)

Ein TLS-Verbindungszustand (TLS connection state) ist die Betriebsumgebung des TLS-Record-Protokolls. Er spezifiziert einen Komprimierungsalgorithmus, einen Verschlüsselungsalgorithmus und einen MAC-Algorithmus. Darüber hinaus sind die Parameter für diese Algorithmen bekannt: der MAC-Schlüssel und die Bulk-Verschlüsselungsschlüssel für die Verbindung in Lese- und Schreibrichtung. Logischerweise gibt es immer vier ausstehende Verbindungszustände: die aktuellen Lese- und Schreibzustände und die ausstehenden Lese- und Schreibzustände. Alle Records werden unter den aktuellen Lese- und Schreibzuständen verarbeitet. Die Sicherheitsparameter für die ausstehenden Zustände können von den TLS-Handshake-Protokollen gesetzt werden, und das ChangeCipherSpec kann selektiv einen der ausstehenden Zustände zum aktuellen machen, wobei der entsprechende aktuelle Zustand verworfen und durch den ausstehenden Zustand ersetzt wird; der ausstehende Zustand wird dann auf einen leeren Zustand reinitialisiert. Es ist illegal, einen Zustand, der nicht mit Sicherheitsparametern initialisiert wurde, zum aktuellen Zustand zu machen. Der anfängliche aktuelle Zustand spezifiziert immer, dass keine Verschlüsselung, Komprimierung oder MAC verwendet wird.

Die Sicherheitsparameter für einen TLS-Verbindungs-Lese- und Schreibzustand werden durch Bereitstellung der folgenden Werte gesetzt:

connection end (Verbindungsende)

  • Ob diese Entität in dieser Verbindung als "Client" oder "Server" betrachtet wird.

PRF algorithm (PRF-Algorithmus)

  • Ein Algorithmus, der verwendet wird, um Schlüssel aus dem Master Secret zu generieren (siehe Abschnitte 5 und 6.3).

bulk encryption algorithm (Bulk-Verschlüsselungsalgorithmus)

  • Ein Algorithmus, der für die Bulk-Verschlüsselung verwendet werden soll. Diese Spezifikation umfasst die Schlüsselgröße dieses Algorithmus, ob es sich um eine Block-, Stream- oder AEAD-Verschlüsselung handelt, die Blockgröße der Verschlüsselung (falls zutreffend) und die Längen der expliziten und impliziten Initialisierungsvektoren (oder Nonces).

MAC algorithm (MAC-Algorithmus)

  • Ein Algorithmus, der für die Nachrichtenauthentifizierung verwendet werden soll. Diese Spezifikation umfasst die Größe des vom MAC-Algorithmus zurückgegebenen Werts.

compression algorithm (Komprimierungsalgorithmus)

  • Ein Algorithmus, der für die Datenkomprimierung verwendet werden soll. Diese Spezifikation muss alle Informationen enthalten, die der Algorithmus zur Durchführung der Komprimierung benötigt.

master secret (Master Secret)

  • Ein 48-Byte-Geheimnis, das zwischen den beiden Peers in der Verbindung geteilt wird.

client random (Client-Zufallszahl)

  • Ein vom Client bereitgestellter 32-Byte-Wert.

server random (Server-Zufallszahl)

  • Ein vom Server bereitgestellter 32-Byte-Wert.

Diese Parameter sind in der Präsentationssprache wie folgt definiert:

enum { server, client } ConnectionEnd;

enum { tls_prf_sha256 } PRFAlgorithm;

enum { null, rc4, 3des, aes }
BulkCipherAlgorithm;

enum { stream, block, aead } CipherType;

enum { null, hmac_md5, hmac_sha1, hmac_sha256,
hmac_sha384, hmac_sha512} MACAlgorithm;

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

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

struct {
ConnectionEnd entity;
PRFAlgorithm prf_algorithm;
BulkCipherAlgorithm bulk_cipher_algorithm;
CipherType cipher_type;
uint8 enc_key_length;
uint8 block_length;
uint8 fixed_iv_length;
uint8 record_iv_length;
MACAlgorithm mac_algorithm;
uint8 mac_length;
uint8 mac_key_length;
CompressionMethod compression_algorithm;
opaque master_secret[48];
opaque client_random[32];
opaque server_random[32];
} SecurityParameters;

Die Record-Schicht verwendet die Sicherheitsparameter, um die folgenden sechs Elemente zu generieren (einige davon werden nicht von allen Verschlüsselungen benötigt und sind daher leer):

  • client write MAC key (Client-Schreib-MAC-Schlüssel)
  • server write MAC key (Server-Schreib-MAC-Schlüssel)
  • client write encryption key (Client-Schreib-Verschlüsselungsschlüssel)
  • server write encryption key (Server-Schreib-Verschlüsselungsschlüssel)
  • client write IV (Client-Schreib-IV)
  • server write IV (Server-Schreib-IV)

Die Client-Schreibparameter werden vom Server beim Empfangen und Verarbeiten von Records verwendet und umgekehrt. Der Algorithmus zum Generieren dieser Elemente aus den Sicherheitsparametern wird in Abschnitt 6.3 beschrieben.

Sobald die Sicherheitsparameter gesetzt und die Schlüssel generiert wurden, können die Verbindungszustände instantiiert werden, indem sie zu aktuellen Zuständen gemacht werden. Diese aktuellen Zustände MÜSSEN (MUST) für jeden verarbeiteten Record aktualisiert werden. Jeder Verbindungszustand umfasst die folgenden Elemente:

compression state (Komprimierungszustand)

  • Der aktuelle Zustand des Komprimierungsalgorithmus.

cipher state (Verschlüsselungszustand)

  • Der aktuelle Zustand des Verschlüsselungsalgorithmus. Dies umfasst den geplanten Schlüssel für diese Verbindung. Für Stream-Verschlüsselungen enthält dies auch alle Zustandsinformationen, die erforderlich sind, damit der Stream Daten weiterhin verschlüsseln oder entschlüsseln kann.

MAC key (MAC-Schlüssel)

  • Der MAC-Schlüssel für diese Verbindung, wie oben generiert.

sequence number (Sequenznummer)

  • Jeder Verbindungszustand enthält eine Sequenznummer, die für Lese- und Schreibzustände separat verwaltet wird. Die Sequenznummer MUSS (MUST) auf Null gesetzt werden, wenn ein Verbindungszustand zum aktiven Zustand wird. Sequenznummern sind vom Typ uint64 und dürfen 2^64-1 nicht überschreiten. Sequenznummern wickeln sich nicht um. Wenn eine TLS-Implementierung eine Sequenznummer umbrechen müsste, muss sie stattdessen neu verhandeln. Eine Sequenznummer wird nach jedem Record inkrementiert: Insbesondere MUSS (MUST) der erste unter einem bestimmten Verbindungszustand übertragene Record die Sequenznummer 0 verwenden.

6.2. Record-Schicht (Record Layer)

Die TLS-Record-Schicht empfängt nicht interpretierte Daten von höheren Schichten in nicht-leeren Blöcken beliebiger Größe.

6.2.1. Fragmentierung (Fragmentation)

Die Record-Schicht fragmentiert Informationsblöcke in TLSPlaintext-Records, die Daten in Chunks von 2^14 Bytes oder weniger tragen. Client-Nachrichtengrenzen werden in der Record-Schicht nicht beibehalten (d. h. mehrere Client-Nachrichten desselben ContentType KÖNNEN (MAY) in einen einzelnen TLSPlaintext-Record zusammengeführt werden, oder eine einzelne Nachricht KANN (MAY) über mehrere Records fragmentiert werden).

struct {
uint8 major;
uint8 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

  • Das höhere Protokoll, das verwendet wird, um das eingeschlossene Fragment zu verarbeiten.

version

  • Die Version des verwendeten Protokolls. Dieses Dokument beschreibt TLS Version 1.2, die die Version 3 verwendet. Der Versionswert 3.3 ist historisch und leitet sich von der Verwendung von 1 für TLS 1.0 ab. (Siehe Anhang A.1.) Beachten Sie, dass ein Client, der mehrere Versionen von TLS unterstützt, möglicherweise nicht weiß, welche Version verwendet wird, bevor er das ServerHello empfängt. Siehe Anhang E für eine Diskussion darüber, welche Record-Layer-Versionsnummer das ClientHello verwenden sollte.

length

  • Die Länge (in Bytes) des folgenden TLSPlaintext.fragment. Die Länge DARF NICHT (MUST NOT) 2^14 überschreiten.

fragment

  • Die Anwendungsdaten. Diese Daten sind transparent und werden als unabhängiger Block behandelt, der vom höheren Protokoll verarbeitet werden soll, das durch das type-Feld angegeben wird.

Implementierungen DÜRFEN NICHT (MUST NOT) Null-Längen-Fragmente von Handshake-, Alert- oder ChangeCipherSpec-Inhaltstypen senden. Null-Längen-Fragmente von Anwendungsdaten KÖNNEN (MAY) gesendet werden, da sie potenziell als Traffic-Analyse-Gegenmaßnahme nützlich sind.

Hinweis: Daten verschiedener TLS-Record-Layer-Inhaltstypen KÖNNEN (MAY) verschachtelt werden. Anwendungsdaten haben im Allgemeinen eine niedrigere Priorität für die Übertragung als andere Inhaltstypen. Records DÜRFEN jedoch NICHT (MUST NOT) ChangeCipherSpec-Nachrichtengrenzen überschreiten.

6.2.2. Record-Komprimierung und -Dekomprimierung (Record Compression and Decompression)

Alle Records werden mit dem im aktuellen Sitzungszustand definierten Komprimierungsalgorithmus komprimiert. Es gibt immer einen aktiven Komprimierungsalgorithmus; er ist jedoch anfänglich als CompressionMethod.null definiert. Der Komprimierungsalgorithmus übersetzt eine TLSPlaintext-Struktur in eine TLSCompressed-Struktur. Die Komprimierung muss verlustfrei sein und darf die Inhaltslänge nicht um mehr als 1024 Bytes erhöhen. Wenn die Dekomprimierungsfunktion auf ein TLSCompressed.fragment stößt, das sich zu einer Länge von mehr als 2^14 Bytes dekomprimieren würde, MUSS (MUST) sie einen fatalen decompression_failure-Alert melden.

struct {
ContentType type;
ProtocolVersion version;
uint16 length;
opaque fragment[TLSCompressed.length];
} TLSCompressed;

length

  • Die Länge (in Bytes) des folgenden TLSCompressed.fragment. Die Länge DARF NICHT (MUST NOT) 2^14 + 1024 überschreiten.

fragment

  • Die komprimierte Form von TLSPlaintext.fragment.

Hinweis: Eine CompressionMethod.null-Operation ist eine Identitätsoperation; keine Felder werden geändert.

Implementierungshinweis: Dekomprimierungsfunktionen sind dafür verantwortlich sicherzustellen, dass Nachrichten keine internen Pufferüberläufe verursachen können.

6.2.3. Record-Payload-Schutz (Record Payload Protection)

Die Verschlüsselungs- und MAC-Funktionen übersetzen eine TLSCompressed-Struktur in ein TLSCiphertext. Die Entschlüsselungsfunktionen kehren den Prozess um. Der MAC des Records enthält auch eine Sequenznummer, sodass fehlende, zusätzliche oder wiederholte Nachrichten erkennbar sind.

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

type

  • Das type-Feld ist identisch mit TLSCompressed.type.

version

  • Das version-Feld ist identisch mit TLSCompressed.version.

length

  • Die Länge (in Bytes) des folgenden TLSCiphertext.fragment. Die Länge DARF NICHT (MUST NOT) 2^14 + 2048 überschreiten.

fragment

  • Die verschlüsselte Form von TLSCompressed.fragment mit dem MAC.

6.2.3.1. Null- oder Standard-Stream-Verschlüsselung (Null or Standard Stream Cipher)

Stream-Verschlüsselungen (einschließlich BulkCipherAlgorithm.null; siehe Anhang A.6) konvertieren TLSCompressed.fragment-Strukturen in und aus Stream-TLSCiphertext.fragment-Strukturen.

stream-ciphered struct {
opaque content[TLSCompressed.length];
opaque MAC[SecurityParameters.mac_length];
} GenericStreamCipher;

Der MAC wird wie folgt generiert:

MAC(MAC_write_key, seq_num +
TLSCompressed.type +
TLSCompressed.version +
TLSCompressed.length +
TLSCompressed.fragment);

wobei "+" die Verkettung bezeichnet.

seq_num

  • Die Sequenznummer für diesen Record.

MAC

  • Der in SecurityParameters.mac_algorithm spezifizierte MAC-Algorithmus.

Beachten Sie, dass der MAC vor der Verschlüsselung berechnet wird. Die Stream-Verschlüsselung verschlüsselt den gesamten Block einschließlich des MAC.

6.2.3.2. CBC-Block-Verschlüsselung (CBC Block Cipher)

Für Block-Verschlüsselungen (wie 3DES oder AES) konvertieren die Verschlüsselungs- und MAC-Funktionen TLSCompressed.fragment-Strukturen in und aus Block-TLSCiphertext.fragment-Strukturen.

struct {
opaque IV[SecurityParameters.record_iv_length];
block-ciphered struct {
opaque content[TLSCompressed.length];
opaque MAC[SecurityParameters.mac_length];
uint8 padding[GenericBlockCipher.padding_length];
uint8 padding_length;
};
} GenericBlockCipher;

Der MAC wird wie in Abschnitt 6.2.3.1 beschrieben generiert.

IV

  • Der Initialisierungsvektor (IV) SOLLTE (SHOULD) zufällig gewählt werden und MUSS (MUST) unvorhersagbar sein. Beachten Sie, dass es in Versionen von TLS vor 1.1 kein IV-Feld gab und der letzte Chiffretextblock des vorherigen Records (das "CBC-Residuum") als IV verwendet wurde. Dies wurde geändert, um die in [CBCATT] beschriebenen Angriffe zu verhindern. Für Block-Verschlüsselungen beträgt die IV-Länge SecurityParameters.record_iv_length, was SecurityParameters.block_length entspricht.

padding

  • Padding, das hinzugefügt wird, um die Länge des Klartexts zu einem ganzzahligen Vielfachen der Blocklänge der Block-Verschlüsselung zu zwingen. Das Padding KANN (MAY) eine beliebige Länge von bis zu 255 Bytes haben, solange es dazu führt, dass TLSCiphertext.length ein ganzzahliges Vielfaches der Blocklänge ist. Längere als notwendige Längen können wünschenswert sein, um Angriffe auf ein Protokoll zu vereiteln, die auf der Analyse der Längen ausgetauschter Nachrichten basieren. Jedes uint8 im Padding-Datenvektor MUSS (MUST) mit dem Padding-Längenwert gefüllt werden. Der Empfänger MUSS (MUST) dieses Padding prüfen und MUSS (MUST) einen bad_record_mac-Alert zurückgeben, wenn das Padding nicht korrekt ist. Der Empfänger SOLLTE (SHOULD) das Padding so wenig wie möglich untersuchen, um eine möglichst einheitliche Antwortzeit bereitzustellen, unabhängig davon, ob das Padding korrekt ist oder nicht.

padding_length

  • Die Padding-Länge MUSS (MUST) so sein, dass die Gesamtgröße der GenericBlockCipher-Struktur ein Vielfaches der Blocklänge der Verschlüsselung ist. Zulässige Werte reichen von Null bis 255 einschließlich. Diese Länge gibt die Länge des Padding-Felds exklusive des padding_length-Felds selbst an.

Die verschlüsselte Datenlänge (TLSCiphertext.length) ist eins größer als die Summe von SecurityParameters.block_length, TLSCompressed.length, SecurityParameters.mac_length und padding_length.

Beispiel: Wenn die Blocklänge 8 Bytes beträgt, die Inhaltslänge (TLSCompressed.length) 61 Bytes beträgt und die MAC-Länge 20 Bytes beträgt, beträgt die Länge vor dem Padding 82 Bytes (dies beinhaltet nicht den IV). Daher muss die Padding-Länge modulo 8 gleich 6 sein, um die Gesamtlänge zu einem geraden Vielfachen von 8 Bytes (der Blocklänge) zu machen. Die Padding-Länge kann 6, 14, 22 usw. bis 254 betragen. Wenn die Padding-Länge das notwendige Minimum wäre, 6, würde das Padding 6 Bytes betragen, wobei jedes den Wert 6 enthält. Somit würden die letzten 8 Oktette des GenericBlockCipher vor der Blockverschlüsselung xx 06 06 06 06 06 06 06 lauten, wobei xx das letzte Oktett des MAC ist.

Hinweis: Bei Block-Verschlüsselungen im CBC-Modus (Cipher Block Chaining) ist es kritisch, dass der gesamte Klartext des Records bekannt ist, bevor ein Chiffretext übertragen wird. Andernfalls ist es für den Angreifer möglich, den in [CBCATT] beschriebenen Angriff durchzuführen.

Implementierungshinweis: Canvel et al. [CBCTIME] haben einen Timing-Angriff auf CBC-Padding demonstriert, der auf der zur Berechnung des MAC erforderlichen Zeit basiert. Um sich gegen diesen Angriff zu verteidigen, MÜSSEN (MUST) Implementierungen sicherstellen, dass die Record-Verarbeitungszeit im Wesentlichen gleich ist, unabhängig davon, ob das Padding korrekt ist oder nicht. Im Allgemeinen besteht der beste Weg, dies zu tun, darin, den MAC auch dann zu berechnen, wenn das Padding falsch ist, und das Paket erst dann abzulehnen. Wenn beispielsweise das Padding falsch zu sein scheint, könnte die Implementierung ein Null-Längen-Padding annehmen und dann den MAC berechnen. Dies hinterlässt einen kleinen Timing-Kanal, da die MAC-Leistung bis zu einem gewissen Grad von der Größe des Datenfragments abhängt, aber es wird nicht als groß genug angesehen, um ausgenutzt werden zu können, aufgrund der großen Blockgröße bestehender MACs und der geringen Größe des Timing-Signals.

6.2.3.3. AEAD-Verschlüsselungen (AEAD Ciphers)

Für AEAD-Verschlüsselungen [AEAD] (wie CCM oder GCM) konvertiert die AEAD-Funktion TLSCompressed.fragment-Strukturen in und aus AEAD-TLSCiphertext.fragment-Strukturen.

struct {
opaque nonce_explicit[SecurityParameters.record_iv_length];
aead-ciphered struct {
opaque content[TLSCompressed.length];
};
} GenericAEADCipher;

AEAD-Verschlüsselungen nehmen als Eingabe einen einzelnen Schlüssel, eine Nonce, einen Klartext und "zusätzliche Daten", die in die Authentifizierungsprüfung einbezogen werden sollen, wie in Abschnitt 2.1 von [AEAD] beschrieben. Der Schlüssel ist entweder client_write_key oder server_write_key. Es wird kein MAC-Schlüssel verwendet.

Jede AEAD-Verschlüsselungssuite MUSS (MUST) spezifizieren, wie die der AEAD-Operation zugeführte Nonce konstruiert wird und was die Länge des GenericAEADCipher.nonce_explicit-Teils ist. In vielen Fällen ist es angemessen, die teilweise implizite Nonce-Technik zu verwenden, die in Abschnitt 3.2.1 von [AEAD] beschrieben wird; wobei record_iv_length die Länge des expliziten Teils ist. In diesem Fall SOLLTE (SHOULD) der implizite Teil aus key_block als client_write_iv und server_write_iv abgeleitet werden (wie in Abschnitt 6.3 beschrieben), und der explizite Teil ist in GenericAEADCipher.nonce_explicit enthalten.

Der Klartext ist das TLSCompressed.fragment.

Die zusätzlichen authentifizierten Daten, die wir als additional_data bezeichnen, sind wie folgt definiert:

additional_data = seq_num + TLSCompressed.type +
TLSCompressed.version + TLSCompressed.length;

wobei "+" die Verkettung bezeichnet.

Der aead_output besteht aus dem Chiffretext, der von der AEAD-Verschlüsselungsoperation ausgegeben wird. Die Länge wird im Allgemeinen größer als TLSCompressed.length sein, aber um einen Betrag, der mit der AEAD-Verschlüsselung variiert. Da die Verschlüsselungen Padding einbeziehen können, kann der Betrag des Overheads mit unterschiedlichen TLSCompressed.length-Werten variieren. Jede AEAD-Verschlüsselung DARF NICHT (MUST NOT) eine Erweiterung von mehr als 1024 Bytes erzeugen. Symbolisch:

AEADEncrypted = AEAD-Encrypt(write_key, nonce, plaintext,
additional_data)

Um zu entschlüsseln und zu verifizieren, nimmt die Verschlüsselung den Schlüssel, die Nonce, die "additional_data" und den AEADEncrypted-Wert als Eingabe. Die Ausgabe ist entweder der Klartext oder ein Fehler, der anzeigt, dass die Entschlüsselung fehlgeschlagen ist. Es gibt keine separate Integritätsprüfung. Das heißt:

TLSCompressed.fragment = AEAD-Decrypt(write_key, nonce,
AEADEncrypted,
additional_data)

Wenn die Entschlüsselung fehlschlägt, MUSS (MUST) ein fataler bad_record_mac-Alert generiert werden.

6.3. Schlüsselberechnung (Key Calculation)

Das Record-Protokoll erfordert einen Algorithmus zum Generieren von Schlüsseln, die vom aktuellen Verbindungszustand (siehe Anhang A.6) benötigt werden, aus den vom Handshake-Protokoll bereitgestellten Sicherheitsparametern.

Das Master Secret wird in eine Sequenz sicherer Bytes erweitert, die dann in einen Client-Schreib-MAC-Schlüssel, einen Server-Schreib-MAC-Schlüssel, einen Client-Schreib-Verschlüsselungsschlüssel und einen Server-Schreib-Verschlüsselungsschlüssel aufgeteilt wird. Jeder davon wird aus der Byte-Sequenz in dieser Reihenfolge generiert. Nicht verwendete Werte sind leer. Einige AEAD-Verschlüsselungen können zusätzlich einen Client-Schreib-IV und einen Server-Schreib-IV erfordern (siehe Abschnitt 6.2.3.3).

Wenn Schlüssel und MAC-Schlüssel generiert werden, wird das Master Secret als Entropiequelle verwendet.

Um das Schlüsselmaterial zu generieren, berechnen Sie

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

bis genügend Ausgabe generiert wurde. Dann wird der key_block wie folgt aufgeteilt:

client_write_MAC_key[SecurityParameters.mac_key_length]
server_write_MAC_key[SecurityParameters.mac_key_length]
client_write_key[SecurityParameters.enc_key_length]
server_write_key[SecurityParameters.enc_key_length]
client_write_IV[SecurityParameters.fixed_iv_length]
server_write_IV[SecurityParameters.fixed_iv_length]

Derzeit ist die größte Schlüsselmaterialanforderung für AES_256_CBC_SHA256. Es erfordert 2 x 32 Byte Schlüssel und 2 x 32 Byte MAC-Schlüssel, also insgesamt 128 Byte Schlüsselmaterial. Im Gegensatz dazu reichen die vom Client und Server bereitgestellten Zufallsdaten (insgesamt 64 Bytes) aus. Zusätzliche Daten können auch von der PRF bereitgestellt werden, aber im Fall von TLS 1.2 wird sie immer auf die leere Zeichenfolge gesetzt.

Exportierbare Verschlüsselungsalgorithmen (die nicht mehr unterstützt werden) erforderten eine zusätzliche Verarbeitung, um kürzere Schlüssel aus dem key_block abzuleiten. Export-Verschlüsselungen SOLLTEN NICHT (SHOULD NOT) in neuen Implementierungen verwendet werden.