メインコンテンツまでスキップ

4. TLSメッセージの伝送 (Carrying TLS Messages)

QUIC は、CRYPTO フレームで TLS ハンドシェイクデータを伝送します。各 CRYPTO フレームは、オフセットと長さで識別される、連続したハンドシェイクデータのブロックで構成されます。これらのフレームは QUIC パケットにパッケージ化され、現在の暗号化レベルを使用して暗号化されます。TCP 上の TLS と同様に、TLS ハンドシェイクデータが QUIC に配信されると、QUIC の責任はそれを確実に配信することです。TLS が生成する各データチャンクは、TLS が現在使用している一連の鍵に関連付けられています。QUIC がそのデータを再送信する必要がある場合、TLS がすでに新しい鍵に更新していても、同じ鍵を使用しなければなりません (MUST)。

各暗号化レベルはパケット番号空間に対応します。使用されるパケット番号空間によって、フレームのセマンティクスが決まります。特定のフレームは、異なるパケット番号空間では禁止されています。[QUIC-TRANSPORT] のセクション 12.5 を参照してください。

パケットはネットワーク内で順序が乱れる可能性があるため、QUIC はパケットタイプを使用して、特定のパケットの保護に使用される鍵を示します。異なるタイプのパケットを送信する必要がある場合、エンドポイントは結合パケット (coalesced packets) を使用して、それらを同じ UDP データグラムに入れるべきです (SHOULD)。

表1に示すように、さまざまな暗号化鍵とパケット番号空間の関係を示します。

パケットタイプ暗号化鍵パケット番号空間
InitialInitial secretsInitial
0-RTT Protected0-RTTApplication data
HandshakeHandshakeHandshake
RetryRetryN/A
Version NegotiationN/AN/A
Short Header1-RTTApplication data

表1: パケットタイプ別の暗号化鍵

[QUIC-TRANSPORT] のセクション17は、異なる暗号化レベルのパケットがハンドシェイクプロセスにどのように適合するかを示しています。

4.1. TLS インターフェース (Interface to TLS)

図4に示すように、QUIC から TLS へのインターフェースには4つの主要な機能があります:

  • ハンドシェイクメッセージの送受信
  • 再開セッションから保存されたトランスポート状態とアプリケーション状態を処理し、0-RTT データの生成または受け入れが有効かどうかを決定する
  • 鍵の再生成(送信と受信を含む)
  • ハンドシェイク状態の更新

TLS を構成するために追加の機能が必要になる場合があります。特に、QUIC と TLS は、ピア資格情報の検証(証明書検証 [RFC5280] など)の責任者について合意する必要があります。

4.1.1. ハンドシェイク完了 (Handshake Complete)

本文書では、TLS スタックがハンドシェイク完了を報告したときに、TLS ハンドシェイクが完了したと見なされます。これは、TLS スタックが Finished メッセージを送信し、ピアの Finished メッセージを検証したときに発生します。ピアの Finished メッセージを検証することで、エンドポイントに、以前のハンドシェイクメッセージが変更されていないという保証が提供されます。ハンドシェイクは、両方のエンドポイントで同時に完了するわけではないことに注意してください。したがって、ハンドシェイク完了に基づく要件は、議論されているエンドポイントの観点に依存します。

4.1.2. ハンドシェイク確認 (Handshake Confirmed)

本文書では、ハンドシェイクが完了すると、サーバー上の TLS ハンドシェイクが確認されたと見なされます。サーバーは、ハンドシェイク完了後すぐに HANDSHAKE_DONE フレームを送信しなければなりません (MUST)。クライアントでは、HANDSHAKE_DONE フレームを受信すると、ハンドシェイクが確認されたと見なされます。

さらに、クライアントは、1-RTT パケットの確認応答を受信したときに、ハンドシェイクが確認されたと見なしてもよいです (MAY)。これは、1-RTT 鍵を使用して送信された最低のパケット番号を記録し、受信した任意の 1-RTT ACK フレームの最大確認応答フィールドと比較することで実現できます。後者が前者以上になると、ハンドシェイクが確認されます。

4.1.3. ハンドシェイクメッセージの送受信 (Sending and Receiving Handshake Messages)

ハンドシェイクを推進するために、TLS はハンドシェイクメッセージを送受信する機能に依存しています。このインターフェースには2つの基本的な機能があります。1つは QUIC がハンドシェイクメッセージを要求する機能、もう1つは QUIC がハンドシェイクメッセージを構成するバイトを提供する機能です。

ハンドシェイクを開始する前に、QUIC は TLS に、伝送したいトランスポートパラメータを提供します(セクション 8.2 参照)。

QUIC クライアントは、TLS に TLS ハンドシェイクバイトを要求することで TLS を開始します。クライアントは最初のパケットを送信する前にハンドシェイクバイトを取得します。QUIC サーバーは、クライアントのハンドシェイクバイトを TLS に提供することでこのプロセスを開始します。

任意の時点で、エンドポイントの TLS スタックには、現在の送信暗号化レベルと受信暗号化レベルがあります。TLS 暗号化レベルは、データを保護するために使用される QUIC パケットタイプと鍵を決定します。

各暗号化レベルは、CRYPTO フレームで確実に転送される異なるバイトシーケンスに関連付けられています。TLS が送信するハンドシェイクバイトを提供すると、それらは現在の暗号化レベルのハンドシェイクバイトに追加されます。その後、暗号化レベルによって、生成された CRYPTO フレームを伝送するパケットタイプが決まります(表1参照)。

4つの暗号化レベルが使用され、Initial、0-RTT、Handshake、および 1-RTT パケットの鍵が生成されます。CRYPTO フレームは、0-RTT レベルを除いて、これらのうち3つのレベルでのみ伝送されます。これら4つのレベルは3つのパケット番号空間に対応します:Initial と Handshake 暗号化パケットはそれぞれ独立した空間を使用し、0-RTT と 1-RTT パケットはアプリケーションデータパケット番号空間を使用します。

QUIC は、TLS ハンドシェイクレコードの保護されていないコンテンツを CRYPTO フレームのコンテンツとして扱います。QUIC は TLS レコード保護を使用しません。QUIC は CRYPTO フレームを QUIC パケットに組み立て、これらのパケットは QUIC パケット保護を使用して保護されます。

QUIC CRYPTO フレームは TLS ハンドシェイクメッセージのみを伝送します。TLS アラートは QUIC CONNECTION_CLOSE エラーコードに変換されます(セクション 4.8 参照)。TLS アプリケーションデータやその他のコンテンツタイプは、QUIC によって任意の暗号化レベルで伝送できません。TLS スタックから受信した場合、それはエラーです。

エンドポイントがネットワークから CRYPTO フレームを含む QUIC パケットを受信すると、次のように処理します:

  • パケットが現在の TLS 受信暗号化レベルを使用している場合、データは通常どおり入力ストリームに順番に配置されます。STREAM フレームと同様に、オフセットを使用してデータシーケンス内の正しい位置を見つけます。このプロセスの結果として新しいデータが利用可能になった場合、それは順番に TLS に配信されます。

  • パケットが以前にインストールされた暗号化レベルから来ている場合、そのストリームで以前に受信したデータの末尾を超えるデータを含んではなりません (MUST NOT)。実装は、この要件に違反する動作を PROTOCOL_VIOLATION タイプの接続エラーとして扱わなければなりません (MUST)。

  • パケットが新しい暗号化レベルから来ている場合、TLS が後で処理できるように保存されます。TLS がそのレベルから受信するように移行すると、保存されたデータを TLS に提供できます。TLS がより高い暗号化レベルの鍵を提供したときに、TLS がまだ以前の暗号化レベルからのデータを消費していない場合、これは PROTOCOL_VIOLATION タイプの接続エラーとして扱わなければなりません (MUST)。

新しいデータが TLS に提供されるたびに、TLS から新しいハンドシェイクバイトが要求されます。TLS が受信したハンドシェイクメッセージが不完全であるか、送信するデータがない場合、TLS はバイトを提供しない可能性があります。

CRYPTO フレームのコンテンツは、TLS によって段階的に処理されるか、完全なメッセージまたはフライトが利用可能になるまでバッファリングされる可能性があります。TLS は、順番に到着したハンドシェイクバイトをバッファリングする責任があります。QUIC は、順序が乱れたハンドシェイクバイトまたは準備ができていない暗号化レベルのハンドシェイクバイトをバッファリングする責任があります。QUIC は CRYPTO フレームのフロー制御手段を提供しません([QUIC-TRANSPORT] のセクション 7.5 参照)。

TLS ハンドシェイクが完了すると、QUIC に通知され、TLS が送信する必要がある最終的なハンドシェイクバイトが添付されます。この段階で、ハンドシェイク中にピアがアドバタイズしたトランスポートパラメータが認証されます(セクション 8.2 参照)。

ハンドシェイク完了後、TLS は受動状態になります。TLS は依然としてピアからデータを受信し、それに応じて応答できますが、特定の要求(アプリケーションまたは QUIC による)がない限り、さらにデータを送信する必要はありません。データを送信する理由の1つは、サーバーがクライアントに追加または更新されたセッションチケットを提供したい場合です。

ハンドシェイクが完了すると、QUIC は CRYPTO ストリームに到着したデータを TLS に提供するだけです。受信したデータを提供した後、新しいハンドシェイクメッセージが要求されます。

4.1.4. 暗号化レベルの変更 (Encryption Level Changes)

特定の暗号化レベルの鍵が TLS で利用可能になると、TLS は QUIC にその暗号化レベルの読み取りおよび書き込み鍵が利用可能であることを示します。

新しい鍵が利用可能になることは、常に TLS への入力を提供した結果です。TLS は、初期化時(クライアントによる)または新しいハンドシェイクデータが提供された後にのみ、新しい鍵を提供します。

ただし、TLS 実装はその処理の一部を非同期に実行する場合があります。特に、証明書を検証するプロセスには時間がかかる場合があります。TLS 処理が完了するのを待っている間、エンドポイントは、まだ利用できない鍵を使用して処理される可能性のある受信パケットをバッファリングすべきです (SHOULD)。TLS が鍵を提供すると、これらのパケットを処理できます。エンドポイントは、この期間中に処理できるパケットに応答し続けるべきです (SHOULD)。

入力を処理した後、TLS はハンドシェイクバイト、新しい暗号化レベルの鍵、またはその両方を生成する場合があります。

新しい暗号化レベルが利用可能になると、TLS は QUIC に3つのものを提供します:

  • シークレット (A secret)
  • 関連データ付き認証暗号化 (AEAD) 関数 (An Authenticated Encryption with Associated Data (AEAD) function)
  • 鍵導出関数 (KDF) (A Key Derivation Function (KDF))

これらの値は TLS がネゴシエートした値に基づいており、QUIC がパケットおよびヘッダー保護鍵を生成するために使用されます(セクション5およびセクション 5.4 参照)。

0-RTT が可能な場合、クライアントが TLS ClientHello メッセージを送信した後、またはサーバーがそのメッセージを受信した後に準備ができます。最初のハンドシェイクバイトを QUIC クライアントに提供した後、TLS スタックは 0-RTT 鍵変更のシグナルを発行する場合があります。サーバー側では、ClientHello メッセージを含むハンドシェイクバイトを受信した後、TLS サーバーは 0-RTT 鍵が利用可能であることを示す場合があります。

TLS は一度に1つの暗号化レベルしか使用しませんが、QUIC は複数のレベルを使用できます。たとえば、Finished メッセージ(Handshake 暗号化レベルの CRYPTO フレームを使用)を送信した後、エンドポイントは STREAM データ(1-RTT 暗号化で)を送信できます。Finished メッセージが失われた場合、エンドポイントは Handshake 暗号化レベルを使用して失われたメッセージを再送信します。パケットの順序の乱れや損失は、QUIC が複数の暗号化レベルのパケットを処理する必要があることを意味する場合があります。ハンドシェイク中、これは TLS が現在使用している暗号化レベルよりも高いレベルと低いレベルの両方のパケットを処理する必要がある場合があることを意味します。

特に、サーバー実装は、Handshake 暗号化レベルと 0-RTT 暗号化レベルの両方からデータを同時に読み取ることができる必要があります。クライアントは、Handshake 鍵で保護された ACK フレームを 0-RTT データと交互に配置でき、サーバーは失われた Handshake パケットを検出するためにこれらの確認応答を処理する必要があります。

QUIC は、通常は TLS 実装で利用できない可能性のある鍵へのアクセスも必要とします。たとえば、クライアントは、その暗号化レベルで CRYPTO フレームを送信する準備ができる前に、Handshake パケットを確認する必要がある場合があります。したがって、TLS は、自分自身で使用するために鍵を生成する前に、QUIC に鍵を提供する必要があります。

4.1.5. TLS インターフェースの概要 (TLS Interface Summary)

図5は、クライアントとサーバーの QUIC と TLS 間の交換をまとめたものです。実線の矢印は、ハンドシェイクデータを伝送するパケットを示し、破線の矢印は、アプリケーションデータを送信できる位置を示します。各矢印には、その送信に使用される暗号化レベルがラベル付けされています。

クライアント                                                サーバー
====== ======

ハンドシェイクメッセージを取得
Initial ------------->
送信 0-RTT 鍵をインストール
0-RTT - - - - - - - ->

ハンドシェイクメッセージを受信
ハンドシェイクメッセージを取得
<------------- Initial
受信 0-RTT 鍵をインストール
ハンドシェイク鍵をインストール
ハンドシェイクメッセージを取得
<----------- Handshake
送信 1-RTT 鍵をインストール
<- - - - - - - - 1-RTT

ハンドシェイクメッセージを受信 (Initial)
ハンドシェイク鍵をインストール
ハンドシェイクメッセージを受信 (Handshake)
ハンドシェイクメッセージを取得
Handshake ----------->
ハンドシェイク完了
1-RTT 鍵をインストール
1-RTT - - - - - - - ->

ハンドシェイクメッセージを受信
ハンドシェイク完了
ハンドシェイク確認
受信 1-RTT 鍵をインストール
<--------------- 1-RTT
(HANDSHAKE_DONE)
ハンドシェイク確認

図5: QUIC と TLS 間の相互作用の概要

図5は、単一のメッセージ「フライト」を構成する複数のパケットが個別に処理されることを示すために、どの受信メッセージが異なるアクションをトリガーするかを示しています。これは、異なる暗号化レベルのハンドシェイクメッセージを取得するために、複数回の「ハンドシェイクメッセージを取得」呼び出しを示しています。受信パケットを処理した後、新しいハンドシェイクメッセージが要求されます。

図5は、単純なハンドシェイク交換の1つの可能な構造を示しています。正確なプロセスは、エンドポイント実装の構造とパケットが到着する順序によって異なります。実装は、異なる数の操作を使用したり、他の順序で実行したりできます。

4.2. TLS バージョン (TLS Version)

本文書は、TLS 1.3 [TLS13] を QUIC と共に使用する方法について説明します。

実際には、TLS ハンドシェイクは使用する TLS バージョンをネゴシエートします。両方のエンドポイントがそのバージョンをサポートしている場合、これにより 1.3 より新しい TLS バージョンがネゴシエートされる可能性があります。QUIC で使用される TLS 1.3 機能が新しいバージョンでサポートされている限り、これは許容されます。

クライアントは、1.3 より前の TLS バージョンを提供してはなりません (MUST NOT)。誤って構成された TLS 実装は、TLS 1.2 またはその他の古いバージョンの TLS をネゴシエートする可能性があります。1.3 より前の TLS バージョンがネゴシエートされた場合、エンドポイントは接続を終了しなければなりません (MUST)。

4.3. ClientHello サイズ (ClientHello Size)

クライアントの最初の Initial パケットには、最初の暗号化ハンドシェイクメッセージの開始または全体が含まれます。TLS の場合、これは ClientHello です。サーバーは、新しい受信 QUIC 接続を受け入れるかどうかを決定するために、ClientHello 全体を解析する必要がある場合があります(たとえば、Server Name Identification (SNI) や Application-Layer Protocol Negotiation (ALPN) などの拡張にアクセスする)。ClientHello が複数の Initial パケットにまたがる場合、そのようなサーバーは、クライアントアドレスがまだ検証されていない場合、受信した最初のフラグメントをバッファリングする必要があり、過度のリソースを消費する可能性があります。これを回避するために、サーバーは Retry 機能([QUIC-TRANSPORT] のセクション 8.1 参照)を使用して、検証されたアドレスからのクライアントからの部分的な ClientHello メッセージのみをバッファリングしてもよいです (MAY)。

QUIC パケットとフレーム構造は、ClientHello メッセージに少なくとも36バイトのオーバーヘッドを追加します。クライアントが選択した Source Connection ID フィールドの長さがゼロバイトより大きい場合、オーバーヘッドは増加します。オーバーヘッドには、トークン (token) または 8 バイトより大きい Destination Connection ID も含まれません。これらは両方とも、サーバーが Retry パケットを送信した場合に必要になる可能性があります。

典型的な TLS ClientHello は、1200バイトのパケットに簡単に収まります。ただし、QUIC が追加するオーバーヘッドに加えて、この制限を超える原因となる可能性のあるいくつかの変数があります。大きなセッションチケット、複数または大きな鍵共有、およびサポートされる暗号スイート、署名アルゴリズム、バージョン、QUIC トランスポートパラメータ、およびその他のネゴシエート可能なパラメータと拡張の冗長なリストはすべて、このメッセージを大きくする可能性があります。

サーバーの場合、接続 ID とトークンに加えて、TLS セッションチケットのサイズもクライアントが効率的に接続できる能力に影響します。これらの値のサイズを最小化すると、クライアントがそれらを使用してもClientHello 全体を最初の Initial パケットに収めることができる可能性が高くなります。

TLS 実装は、Initial パケットを伝送するデータグラムの QUIC 要件を満たすのに十分な大きさの ClientHello を確保する必要はありません([QUIC-TRANSPORT] のセクション 14.1 参照)。QUIC 実装は、PADDING フレームまたはパケット結合を使用して、データグラムが十分に大きいことを確認します。

4.4. ピア認証 (Peer Authentication)

認証要件は、使用されるアプリケーションプロトコルによって異なります。TLS はサーバー認証を提供し、サーバーがクライアント認証を要求できるようにします。

クライアントは、サーバーの ID を認証しなければなりません (MUST)。これには通常、サーバーの ID が証明書に含まれていること、および証明書が信頼できるエンティティによって発行されたことを確認することが含まれます(たとえば、[RFC2818] 参照)。

| 注: サーバーが認証のために証明書を提供する場合、証明書チェーンのサイズが大量のバイトを消費する可能性があります。 | 証明書チェーンのサイズを制御することは、QUIC のパフォーマンスにとって重要です。なぜなら、クライアントアドレスを検証する前に、 | サーバーは受信した1バイトごとに最大3バイトしか送信できないためです([QUIC-TRANSPORT] のセクション 8.1 参照)。 | 証明書チェーンのサイズは、名前または拡張の数を制限することで管理できます。ECDSA など、小さな公開鍵表現を持つ鍵を使用する。 | または証明書圧縮 [COMPRESS] を使用します。

サーバーは、ハンドシェイク中にクライアント認証を要求してもよいです (MAY)。要求されたときにクライアントが認証できない場合、サーバーは接続を拒否してもよいです (MAY)。クライアント認証の要件は、アプリケーションプロトコルと展開によって異なります。

サーバーは、ハンドシェイク後のクライアント認証([TLS13] のセクション 4.6.2 で定義)を使用してはなりません (MUST NOT)。なぜなら、QUIC が提供する多重化により、クライアントが証明書要求をそれをトリガーしたアプリケーション層イベントに関連付けることができなくなるためです([HTTP2-TLS13] 参照)。より具体的には、サーバーは、ハンドシェイク後の TLS CertificateRequest メッセージを送信してはならず (MUST NOT)、クライアントはそのようなメッセージを受信することを PROTOCOL_VIOLATION タイプの接続エラーとして扱わなければなりません (MUST)。

4.5. セッション再開 (Session Resumption)

QUIC は、TLS 1.3 のセッション再開機能を使用できます。これは、ハンドシェイク完了後に CRYPTO フレームで NewSessionTicket メッセージを伝送することで実現されます。セッション再開は、0-RTT を提供するために使用でき、0-RTT が無効になっている場合にも使用できます。

セッション再開を使用するエンドポイントは、再開接続を作成するときに現在の接続に関するいくつかの情報を記憶する必要がある場合があります。TLS は、いくつかの情報を保持することを要求します([TLS13] のセクション 4.6.1 参照)。0-RTT も使用されていない限り、QUIC 自体は再開接続間で任意の状態を保持することに依存しません([QUIC-TRANSPORT] のセクション 7.4.1 およびセクション 4.6.1 参照)。アプリケーションプロトコルは、再開接続間で保持される状態に依存する場合があります。

クライアントは、再開に必要なすべての状態をセッションチケットと一緒に保存できます。サーバーは、セッションチケットを使用して状態を運ぶのを支援できます。

セッション再開により、サーバーは元の接続でのアクティビティを再開された接続に関連付けることができ、クライアントにとってプライバシーの問題を引き起こす可能性があります。クライアントは、この関連を作成しないように、再開を有効にしないことを選択できます。クライアントは、チケットを繰り返し使用すべきではありません (SHOULD NOT)。なぜなら、これによりサーバー以外のエンティティが接続を関連付けることができるためです([TLS13] の付録 C.4 参照)。

4.6. 0-RTT

QUIC の 0-RTT 機能により、クライアントはハンドシェイクが完了する前にアプリケーションデータを送信できます。これは、以前の接続からネゴシエートされたパラメータを再利用することで可能になります。この機能を有効にするために、0-RTT は、クライアントが主要なパラメータを記憶し、サーバーが同じ情報を復元できるようにする TLS セッションチケットをサーバーに提供することに依存しています。

この情報には、TLS 状態([TLS13] によって管理)を決定するパラメータ、QUIC トランスポートパラメータ、選択されたアプリケーションプロトコル、およびアプリケーションプロトコルが必要とする可能性のある任意の情報が含まれます(セクション 4.6.3 参照)。この情報は、0-RTT パケットとそのコンテンツの形成方法を決定します。

同じ情報が両方のエンドポイントで利用可能であることを確認するために、0-RTT を確立するために使用されるすべての情報は、同じ接続から取得されます。エンドポイントは、0-RTT の送信または処理を変更する可能性のある情報を選択的に無視することはできません。

[TLS13] は、元の接続と 0-RTT を使用しようとする試みの間の時間に7日間の制限を設定します。0-RTT の使用には、特に潜在的なリプレイ攻撃によって露呈されるものから生じる他の制限があります(セクション 9.2 参照)。

4.6.1. 0-RTT の有効化 (Enabling 0-RTT)

NewSessionTicket メッセージの TLS early_data 拡張は、サーバーが受け入れる TLS 0-RTT データの量を伝達するために定義されています(max_early_data_size パラメーターで)。QUIC は TLS 早期データを使用しません。QUIC は 0-RTT データパケットを使用して早期データを伝送します。したがって、max_early_data_size パラメーターは、サーバーが QUIC 0-RTT データを受け入れることを示すために、センチネル値 0xffffffff を保持するように再利用されます。サーバーが 0-RTT データを受け入れないことを示すには、NewSessionTicket から early_data 拡張を省略します。クライアントが QUIC 0-RTT で送信できるデータ量は、サーバーが提供する initial_max_data トランスポートパラメーターによって制御されます。

サーバーは、max_early_data_size フィールドが 0xffffffff 以外の任意の値に設定された early_data 拡張を送信してはなりません (MUST NOT)。クライアントは、他の任意の値を持つ early_data 拡張を含む NewSessionTicket を受信することを PROTOCOL_VIOLATION タイプの接続エラーとして扱わなければなりません (MUST)。

0-RTT データパケットを送信したいクライアントは、後続のハンドシェイクの ClientHello メッセージで early_data 拡張を使用します([TLS13] のセクション 4.2.10 参照)。次に、0-RTT データパケットでアプリケーションデータを送信します。

サーバーが NEW_TOKEN フレームを送信した場合、0-RTT を試みるクライアントはアドレス検証トークンも提供してもよいです (MAY)([QUIC-TRANSPORT] のセクション 8.1 参照)。

4.6.2. 0-RTT の受け入れと拒否 (Accepting and Rejecting 0-RTT)

サーバーは、EncryptedExtensions で early_data 拡張を送信することにより 0-RTT を受け入れます([TLS13] のセクション 4.2.10 参照)。次に、サーバーは受信した 0-RTT データパケットを処理し、確認します。

サーバーは、early_data 拡張なしで EncryptedExtensions を送信することにより 0-RTT を拒否します。サーバーが TLS HelloRetryRequest を送信すると、常に 0-RTT を拒否します。0-RTT を拒否する場合、サーバーは、処理できたとしても、0-RTT データパケットを処理してはなりません (MUST NOT)。0-RTT が拒否されたとき、クライアントがこれを検出できる場合、0-RTT データパケットの確認を受信することを PROTOCOL_VIOLATION タイプの接続エラーとして扱うべきです (SHOULD)。

0-RTT が拒否されると、クライアントが想定したすべての接続特性が正しくない可能性があります。これには、アプリケーションプロトコルの選択、トランスポートパラメータ、および任意のアプリケーション構成が含まれます。したがって、クライアントは、これらのストリームにバインドされたアプリケーション状態を含むすべてのストリームの状態をリセットしなければなりません (MUST)。

クライアントが Retry または Version Negotiation パケットを受信した場合、0-RTT を再試行してもよいです (MAY)。これらのパケットは 0-RTT の拒否を示すものではありません。

4.6.3. 0-RTT 構成の検証 (Validating 0-RTT Configuration)

サーバーが early_data 拡張を含む ClientHello を受信すると、クライアントからの 0-RTT データを受け入れるか拒否するかを決定する必要があります。決定の一部は TLS スタックによって行われます(たとえば、再開される暗号スイートが ClientHello に含まれているかどうかのチェック。[TLS13] のセクション 4.2.10 参照)。TLS スタックが 0-RTT データを拒否する理由がない場合でも、再開セッションに関連付けられたトランスポートまたはアプリケーションの構成がサーバーの現在の構成と互換性がないため、QUIC スタックまたは QUIC を使用するアプリケーションプロトコルは 0-RTT データを拒否する場合があります。

QUIC は、追加のトランスポート状態を 0-RTT セッションチケットに関連付けることを要求します。一般的な実装方法は、ステートレスセッションチケットを使用し、この状態をセッションチケットに保存することです。QUIC を使用するアプリケーションプロトコルは、関連または保存状態に対して同様の要件を持つ場合があります。この関連状態は、0-RTT データを拒否する必要があるかどうかを決定するために使用されます。たとえば、HTTP/3 設定 [QUIC-HTTP] は、クライアントからの 0-RTT データの解釈方法を決定します。QUIC を使用する他のアプリケーションは、0-RTT データを受け入れるか拒否するかを決定するための異なる要件を持つ場合があります。

4.7. HelloRetryRequest

HelloRetryRequest メッセージ([TLS13] のセクション 4.1.4 参照)は、クライアントに新しい情報(鍵共有など)の提供を要求したり、クライアントの特定の特性を検証したりするために使用できます。QUIC の観点からは、HelloRetryRequest は Initial パケットで伝送される他の暗号化ハンドシェイクメッセージと違いはありません。原則としてこの機能をアドレス検証に使用できますが、QUIC 実装は代わりに Retry を使用すべきです (SHOULD)([QUIC-TRANSPORT] のセクション 8.1 参照)。

4.8. TLS エラー (TLS Errors)

TLS がエラーに遭遇した場合、[TLS13] のセクション6で定義された対応するアラートを生成します。

TLS アラートは QUIC 接続エラーに変換されます。AlertDescription 値に 0x0100 を追加して、CRYPTO_ERROR 範囲内の QUIC エラーコードを生成します([QUIC-TRANSPORT] のセクション 20.1 参照)。生成された値は、タイプ 0x1c の QUIC CONNECTION_CLOSE フレームで送信されます。

QUIC は「致命的 (fatal)」レベルのアラートのみを伝達できます。TLS 1.3 では、「警告 (warning)」レベルの唯一の既存の使用法は、接続の終了を示すためです([TLS13] のセクション 6.1 参照)。QUIC は接続終了の代替手段を提供し、TLS 接続はエラーに遭遇した場合にのみ閉じられるため、QUIC エンドポイントは TLS からの任意のアラートを「致命的」レベルとして扱わなければなりません (MUST)。

QUIC では、特定のエラーコードの代わりに一般的なコードを使用できます([QUIC-TRANSPORT] のセクション11参照)。TLS アラートの場合、これには一般的なアラート(handshake_failure など(QUIC では 0x0128))で任意のアラートを置き換えることが含まれます。エンドポイントは、機密情報を公開する可能性を避けるために、一般的なエラーコードを使用してもよいです (MAY)。

4.9. 未使用鍵の破棄 (Discarding Unused Keys)

QUIC が新しい暗号化レベルへの移行を完了すると、以前の暗号化レベルのパケット保護鍵を破棄できます。これは、ハンドシェイク中に数回発生し、鍵更新時にも発生します(セクション6参照)。

パケット保護鍵は、新しい鍵が利用可能になったときにすぐには破棄されません。低い暗号化レベルのパケットに CRYPTO フレームが含まれている場合、そのデータを再送信するフレームは同じ暗号化レベルで送信されなければなりません (MUST)。同様に、エンドポイントはパケットの確認を生成しますが、その暗号化レベルは確認されるパケットと同じです。したがって、新しい暗号化レベルの鍵が利用可能になった後、短期間、低い暗号化レベルの鍵が必要になる場合があります。

エンドポイントは、特定の暗号化レベルのすべての暗号化ハンドシェイクメッセージをピアから受信し、ピアも同じことを完了したと判断しない限り、その暗号化レベルの鍵を破棄できません。Initial 鍵(セクション 4.9.1)および Handshake 鍵(セクション 4.9.2)については、異なる決定方法が提供されています。これらの方法は、ピアがまだすべての必要な確認を受信していない可能性があるため、その暗号化レベルでパケットを受信または送信することを妨げるものではありません。

エンドポイントは古い鍵を保持する場合がありますが、新しいデータは現在利用可能な最高の暗号化レベルで送信されなければなりません (MUST)。以前の暗号化レベルで送信されるのは、ACK フレームと CRYPTO フレーム内のデータの再送信のみです。これらのパケットには PADDING フレームも含まれる場合があります (MAY)。

4.9.1. 初期鍵の破棄 (Discarding Initial Keys)

Initial 秘密(セクション 5.2)によって保護されたパケットは認証されておらず、攻撃者がパケットを偽造して接続を妨害する可能性があることを意味します。これらの攻撃を制限するために、Initial パケット保護鍵は他の鍵よりも積極的に破棄されます。

Handshake パケットの正常な使用は、Initial パケットの交換が不要になったことを示します。これらの鍵は、Initial パケット内のすべての CRYPTO フレームを受信した後にのみ生成できるためです。したがって、クライアントは、Handshake パケットを最初に送信するときに Initial 鍵を破棄しなければならず (MUST)、サーバーは、Handshake パケットを最初に正常に処理するときに Initial 鍵を破棄しなければなりません (MUST)。その後、エンドポイントは Initial パケットを送信してはなりません (MUST NOT)。

これにより、Initial 暗号化レベルの損失回復状態が放棄され、未処理の Initial パケットは無視されます。

4.9.2. ハンドシェイク鍵の破棄 (Discarding Handshake Keys)

エンドポイントは、TLS ハンドシェイクが確認されたとき(セクション 4.1.2)に Handshake 鍵を破棄しなければなりません (MUST)。

4.9.3. 0-RTT 鍵の破棄 (Discarding 0-RTT Keys)

0-RTT と 1-RTT パケットは同じパケット番号空間を共有し、クライアントは 1-RTT パケットを送信した後に 0-RTT パケットを送信しません(セクション 5.6)。

したがって、クライアントは、1-RTT 鍵をインストールした後すぐに 0-RTT 鍵を破棄すべきです (SHOULD)。その後、それらは役に立たなくなります。

さらに、サーバーは、1-RTT パケットを受信した後すぐに 0-RTT 鍵を破棄してもよいです (MAY)。ただし、パケットの順序が乱れているため、0-RTT パケットは 1-RTT パケットの後に到着する可能性があります。サーバーは、1-RTT 鍵を使用してコンテンツを再送信することなく、順序が乱れたパケットを解読できるように、一時的に 0-RTT 鍵を保持してもよいです (MAY)。1-RTT パケットを受信した後、サーバーは短時間内に 0-RTT 鍵を破棄しなければなりません (MUST)。推奨される (RECOMMENDED) 時間は、プローブタイムアウト (PTO) の3倍です([QUIC-RECOVERY] 参照)。サーバーがすべての 0-RTT データを受信したと判断した場合(失われたパケット番号を追跡することで可能)、サーバーはより早く 0-RTT 鍵を破棄してもよいです (MAY)。