Zum Hauptinhalt springen

7. Die TLS-Handshake-Protokolle (The TLS Handshaking Protocols)

Das TLS-Handshake-Protokoll (TLS Handshake Protocol) ist für folgende Funktionen verantwortlich:

  • Aushandlung der TLS-Version und der Verschlüsselungssuite
  • Server- und Client-Authentifizierung
  • Aushandlung von Verschlüsselungsparametern und Schlüsseln
  • Erkennung von Übertragungsfehlern

Das Handshake-Protokoll besteht aus drei Unterprotokollen:

7.1. Change Cipher Spec-Protokoll

Das Change Cipher Spec-Protokoll (Change Cipher Spec Protocol) wird verwendet, um dem Peer mitzuteilen, dass nachfolgende Records unter der neu ausgehandelten CipherSpec und den Schlüsseln geschützt werden. Das Protokoll besteht aus einer einzigen Nachricht, die unter der aktuellen (nicht ausstehenden) CipherSpec verschlüsselt und komprimiert wird. Die Nachricht besteht aus einem einzelnen Byte mit dem Wert 1.

struct {
enum { change_cipher_spec(1), (255) } type;
} ChangeCipherSpec;

Die ChangeCipherSpec-Nachricht wird während des Handshakes gesendet, nachdem die Sicherheitsparameter vereinbart wurden. Der Empfänger einer ChangeCipherSpec-Nachricht MUSS (MUST) den ausstehenden Lesezustand auf den aktuellen Lesezustand aktualisieren. Eine Finished-Nachricht wird unmittelbar nach dieser Nachricht gesendet, wobei die neuen Algorithmen, Schlüssel und Secrets verwendet werden. Implementierungen DÜRFEN KEINE (MUST NOT) ChangeCipherSpec-Nachrichten senden, bis der Handshake abgeschlossen ist. Die erste nach dieser Nachricht empfangene Nachricht MUSS (MUST) eine Finished-Nachricht sein.

7.2. Alert-Protokoll (Alert Protocol)

TLS stellt Alert-Nachrichten bereit, um Warnungen an Peer-Entitäten zu übermitteln. Wie bei anderen Nachrichten werden Alert-Nachrichten mit dem aktuellen Verbindungszustand verschlüsselt und komprimiert.

enum { warning(1), fatal(2), (255) } AlertLevel;

enum {
close_notify(0),
unexpected_message(10),
bad_record_mac(20),
decryption_failed_RESERVED(21),
record_overflow(22),
decompression_failure(30),
handshake_failure(40),
no_certificate_RESERVED(41),
bad_certificate(42),
unsupported_certificate(43),
certificate_revoked(44),
certificate_expired(45),
certificate_unknown(46),
illegal_parameter(47),
unknown_ca(48),
access_denied(49),
decode_error(50),
decrypt_error(51),
export_restriction_RESERVED(60),
protocol_version(70),
insufficient_security(71),
internal_error(80),
user_canceled(90),
no_renegotiation(100),
unsupported_extension(110),
(255)
} AlertDescription;

struct {
AlertLevel level;
AlertDescription description;
} Alert;

7.2.1. Schließungswarnungen (Closure Alerts)

Der Client und der Server MÜSSEN (MUST) Schließungsinformationen austauschen, bevor sie die Schreibseite der Verbindung schließen. Jede Partei kann die Schließung ihrer Verbindung initiieren, indem sie einen close_notify-Alert sendet. Jede Partei, die einen Schließungsalert empfängt, MUSS (MUST) sofort aufhören, neue Daten über die Verbindung zu senden. Nach der Übertragung eines close_notify DARF (MUST NOT) eine Implementierung keine Daten über diese Verbindung senden.

7.2.2. Fehlerwarnungen (Error Alerts)

Die Fehlerbehandlung im TLS-Protokoll ist sehr einfach. Wenn ein Fehler erkannt wird, sendet die erkennende Partei eine Nachricht an ihren Peer. Nach der Übertragung oder dem Empfang eines fatalen Alerts MÜSSEN (MUST) beide Parteien die Verbindung sofort schließen. Server und Clients MÜSSEN (MUST) geheime Werte und Schlüssel vergessen, die in fehlgeschlagenen Verbindungen etabliert wurden.

Die folgenden Fehlerwarnungen sind definiert:

  • unexpected_message: Eine unangemessene Nachricht wurde empfangen. Dieser Alert sollte niemals von korrekt implementierten Parteien beobachtet werden.
  • bad_record_mac: Dieser Alert wird zurückgegeben, wenn ein Record mit einem falschen MAC empfangen wird. Diese Nachricht ist immer fatal.
  • record_overflow: Ein TLSCiphertext-Record wurde empfangen, der eine Länge von mehr als 2^14+2048 Bytes hatte, oder ein Record wurde zu einem TLSCompressed-Record mit mehr als 2^14 Bytes entschlüsselt (oder einer anderen ausgehandelten Grenze für den Verbindungszustand). Diese Nachricht ist immer fatal.
  • handshake_failure: Der Empfang einer handshake_failure-Alert-Nachricht zeigt an, dass der Absender nicht in der Lage war, einen akzeptablen Satz von Sicherheitsparametern angesichts der verfügbaren Optionen auszuhandeln.
  • bad_certificate: Ein Zertifikat war beschädigt, enthielt Signaturen, die nicht korrekt verifiziert wurden, usw.
  • unsupported_certificate: Ein Zertifikat war von einem nicht unterstützten Typ.
  • certificate_revoked: Ein Zertifikat wurde von seinem Unterzeichner widerrufen.
  • certificate_expired: Ein Zertifikat ist abgelaufen oder derzeit nicht gültig.
  • certificate_unknown: Ein anderes (nicht spezifiziertes) Problem trat bei der Verarbeitung des Zertifikats auf und machte es inakzeptabel.
  • illegal_parameter: Ein Feld im Handshake war außerhalb des Bereichs oder inkonsistent mit anderen Feldern. Diese Nachricht ist immer fatal.
  • unknown_ca: Eine gültige Zertifikatskette oder Teilkette wurde empfangen, aber das Zertifikat wurde nicht akzeptiert, weil das CA-Zertifikat nicht gefunden werden konnte oder nicht mit einer bekannten, vertrauenswürdigen CA übereinstimmte.
  • access_denied: Ein gültiges Zertifikat wurde empfangen, aber als die Zugriffskontrolle angewendet wurde, entschied der Absender, die Verhandlung nicht fortzusetzen.
  • decode_error: Eine Nachricht konnte nicht dekodiert werden, weil ein Feld außerhalb des angegebenen Bereichs lag oder die Länge der Nachricht falsch war. Diese Nachricht ist immer fatal.
  • decrypt_error: Eine kryptografische Handshake-Operation schlug fehl, einschließlich der Unfähigkeit, eine Signatur korrekt zu verifizieren oder eine Finished-Nachricht zu validieren.
  • protocol_version: Die Protokollversion, die der Peer zu verhandeln versuchte, ist erkannt, wird aber nicht unterstützt.
  • insufficient_security: Wird anstelle von handshake_failure zurückgegeben, wenn eine Verhandlung speziell deshalb fehlgeschlagen ist, weil der Server sicherere Verschlüsselungen benötigt als die vom Client unterstützten.
  • internal_error: Ein interner Fehler, der nichts mit dem Peer oder der Korrektheit des Protokolls zu tun hat (wie ein Speicherzuweisungsfehler), macht es unmöglich, fortzufahren. Diese Nachricht ist immer fatal.
  • user_canceled: Dieser Handshake wird aus einem Grund abgebrochen, der nichts mit einem Protokollfehler zu tun hat.
  • no_renegotiation: Wird von einem Client als Antwort auf eine Hello-Anfrage oder vom Server als Antwort auf ein Client-Hello nach dem ersten Handshake gesendet. Diese Nachricht ist immer eine Warnung.
  • unsupported_extension: Wird von Servern gesendet, die eine Erweiterung nicht verstehen können.

7.3. Übersicht über das Handshake-Protokoll (Handshake Protocol Overview)

Das TLS-Handshake-Protokoll umfasst die folgenden Schritte:

  • Austausch von Hello-Nachrichten, um sich auf Algorithmen zu einigen, Zufallswerte auszutauschen und auf Sitzungswiederaufnahme zu prüfen.
  • Austausch der notwendigen kryptografischen Parameter, damit sich Client und Server auf ein Premaster Secret einigen können.
  • Austausch von Zertifikaten und kryptografischen Informationen, damit sich Client und Server authentifizieren können.
  • Generierung eines Master Secrets aus dem Premaster Secret und den ausgetauschten Zufallswerten.
  • Bereitstellung von Sicherheitsparametern für die Record-Schicht.
  • Ermöglichung, dass Client und Server überprüfen, dass ihr Peer dieselben Sicherheitsparameter berechnet hat und dass der Handshake ohne Manipulation durch einen Angreifer stattgefunden hat.

Hinweis: Dieses Dokument bietet nur einen Überblick über das TLS 1.2-Handshake-Protokoll. Für vollständige technische Details siehe Abschnitt 7.4 und nachfolgende Abschnitte von RFC 5246.

7.4. Handshake-Protokoll (Handshake Protocol)

Das TLS-Handshake-Protokoll ist einer der definierten Clients höherer Ebene der TLS-Record-Schicht. Dieses Protokoll wird verwendet, um die Sicherheitsattribute einer Verbindung auszuhandeln. Handshake-Nachrichten werden der TLS-Record-Schicht bereitgestellt, wo sie in eine oder mehrere TLSPlaintext-Strukturen eingekapselt werden, die gemäß dem aktuellen aktiven Verbindungszustand verarbeitet und übertragen werden.

enum {
hello_request(0), client_hello(1), server_hello(2),
certificate(11), server_key_exchange (12),
certificate_request(13), server_hello_done(14),
certificate_verify(15), client_key_exchange(16),
finished(20), (255)
} HandshakeType;

struct {
HandshakeType msg_type;
uint24 length;
select (HandshakeType) {
case hello_request: HelloRequest;
case client_hello: ClientHello;
case server_hello: ServerHello;
case certificate: Certificate;
case server_key_exchange: ServerKeyExchange;
case certificate_request: CertificateRequest;
case server_hello_done: ServerHelloDone;
case certificate_verify: CertificateVerify;
case client_key_exchange: ClientKeyExchange;
case finished: Finished;
} body;
} Handshake;

Handshake-Protokollnachrichten werden mit expliziten Längen präsentiert und können nicht über Handshake-Record-Grenzen fragmentiert werden. Das heißt, jede Handshake-Nachricht muss entweder vollständig in einen einzigen Handshake-Record passen oder sich über mehrere Handshake-Records erstrecken, wobei jeder Record eine ganzzahlige Anzahl von Handshake-Nachrichten enthält. Empfänger MÜSSEN (MUST) prüfen, dass keine anderen Daten einer Handshake-Nachricht im selben Handshake-Record folgen, es sei denn, diese Daten selbst stellen gültige Handshake-Nachrichten dar.

Für vollständige Handshake-Nachrichtentypen und detaillierte Formate siehe die Unterabschnitte von Abschnitt 7.4 in RFC 5246.