RFC 9001 - TLSを使用したQUICの保護
- ステータス: Proposed Standard
- 発行日: May 2021
- ストリーム: IETF
- エラッタ: エラッタなし
概要 (Abstract)
本文書は、トランスポート層セキュリティ (TLS) を使用して QUIC [QUIC-TRANSPORT] を保護する方法について説明します。
目次 (Contents)
- 1. Introduction (はじめに)
- 2. Notational Conventions (表記規則)
- 3. Protocol Overview (プロトコル概要)
- 4. Carrying TLS Messages (TLSメッセージの伝送)
- 4.1. Interface to TLS (TLSインターフェース)
- 4.1.1. Handshake Complete (ハンドシェイク完了)
- 4.1.2. Handshake Confirmed (ハンドシェイク確認)
- 4.1.3. Sending and Receiving Handshake Messages (ハンドシェイクメッセージの送受信)
- 4.1.4. Encryption Level Changes (暗号化レベルの変更)
- 4.1.5. TLS Interface Summary (TLSインターフェースの概要)
- 4.2. TLS Version (TLSバージョン)
- 4.3. ClientHello Size (ClientHelloサイズ)
- 4.4. Peer Authentication (ピア認証)
- 4.5. Session Resumption (セッション再開)
- 4.6. 0-RTT
- 4.6.1. Enabling 0-RTT (0-RTTの有効化)
- 4.6.2. Accepting and Rejecting 0-RTT (0-RTTの受け入れと拒否)
- 4.6.3. Validating 0-RTT Configuration (0-RTT構成の検証)
- 4.7. HelloRetryRequest
- 4.8. TLS Errors (TLSエラー)
- 4.9. Discarding Unused Keys (未使用鍵の破棄)
- 4.9.1. Discarding Initial Keys (初期鍵の破棄)
- 4.9.2. Discarding Handshake Keys (ハンドシェイク鍵の破棄)
- 4.9.3. Discarding 0-RTT Keys (0-RTT鍵の破棄)
- 5. Packet Protection (パケット保護)
- 5.1. Packet Protection Keys (パケット保護鍵)
- 5.2. Initial Secrets (初期シークレット)
- 5.3. AEAD Usage (AEADの使用)
- 5.4. Header Protection (ヘッダー保護)
- 5.4.1. Header Protection Application (ヘッダー保護の適用)
- 5.4.2. Header Protection Sample (ヘッダー保護サンプル)
- 5.4.3. AES-Based Header Protection (AESベースのヘッダー保護)
- 5.4.4. ChaCha20-Based Header Protection (ChaCha20ベースのヘッダー保護)
- 5.5. Receiving Protected Packets (保護されたパケットの受信)
- 5.6. Use of 0-RTT Keys (0-RTT鍵の使用)
- 5.7. Receiving Out-of-Order Protected Packets (順序外保護パケットの受信)
- 5.8. Retry Packet Integrity (再試行パケットの完全性)
- 6. Key Update (鍵更新)
- 7. Security of Initial Messages (初期メッセージのセキュリティ)
- 8. QUIC-Specific Adjustments to the TLS Handshake (TLSハンドシェイクへのQUIC固有の調整)
- 9. Security Considerations (セキュリティに関する考察)
- 10. IANA Considerations (IANAに関する考察)
- 11. References (参考文献)
付録 (Appendices)
関連リソース
- 公式原文: RFC 9001
- 公式ページ: RFC 9001 DataTracker
- 正誤表: RFC Editor Errata
1. はじめに (Introduction)
本文書は、QUIC [QUIC-TRANSPORT] を TLS [TLS13] で保護する方法について説明します。
TLS 1.3 は、以前のバージョンと比較して、接続確立における重要な遅延改善を提供します。パケット損失がない場合、ほとんどの新しい接続は1往復時間内に確立され、保護されます。同じクライアントとサーバー間の後続の接続では、クライアントは多くの場合、アプリケーションデータを即座に送信できます。これはゼロ往復時間 (0-RTT) 設定を使用します。
本文書は、TLS を QUIC のセキュリティコンポーネントとして使用する方法について説明します。
2. 表記規則 (Notational Conventions)
本文書のキーワード「MUST (しなければならない)」、「MUST NOT (してはならない)」、「REQUIRED (必須である)」、「SHALL (するものとする)」、「SHALL NOT (しないものとする)」、「SHOULD (すべきである)」、「SHOULD NOT (すべきでない)」、「RECOMMENDED (推奨される)」、「NOT RECOMMENDED (推奨されない)」、「MAY (してもよい)」、「OPTIONAL (任意である)」は、BCP 14 [RFC2119] [RFC8174] に記載されているとおりに解釈されるものとします。ただし、ここに示すようにすべて大文字で表示される場合に限ります。
本文書は、[QUIC-TRANSPORT] で確立された用語を使用します。
簡潔にするため、略語 TLS は TLS 1.3 を指すために使用されますが、より新しいバージョンの TLS を使用することもできます。セクション 4.2 を参照してください。
2.1. TLS 概要 (TLS Overview)
TLS は、信頼できない媒体(インターネットなど)を介して2つのエンドポイントが通信方法を確立する手段を提供します。TLS は、ピアを認証し、エンドポイント間で交換されるメッセージに機密性と完全性保護を提供できます。
内部的に、TLS は階層化されたプロトコルであり、その構造は図1に示されています。
+-------------+------------+--------------+---------+
コンテンツ| | | アプリケー | |
層 | ハンド | アラート | ションデータ | ... |
| シェイク | | | |
+-------------+------------+--------------+---------+
レコード | |
層 | レコード |
| |
+---------------------------------------------------+
図1: TLS の階層化
各コンテンツ層メッセージ(ハンドシェイク、アラート、アプリケーションデータなど)は、レコード層によって一連の型付き TLS レコードとして伝送されます。レコードは個別に暗号的に保護され、その後、順序付けと配信保証を提供する信頼性のあるトランスポート(通常は TCP)を介して送信されます。
TLS 認証鍵交換は、クライアントとサーバーという2つのエンドポイント間で行われます。クライアントが交換を開始し、サーバーが応答します。鍵交換が正常に完了すると、クライアントとサーバーの両方が秘密について合意します。TLS は、事前共有鍵 (PSK) と有限体または楕円曲線ベースの Diffie-Hellman ((EC)DHE) 鍵交換の両方をサポートします。PSK は早期データ (0-RTT) の基礎です。後者は、(EC)DHE 鍵が破棄されたときに前方秘匿性 (FS) を提供します。これら2つのモードを組み合わせて、PSK を使用した認証を行いながら前方秘匿性を提供することもできます。
TLS ハンドシェイクが完了すると、クライアントはサーバーの身元を学習し、認証します。サーバーはオプションでクライアントの身元を学習し、認証できます。TLS は、X.509 [RFC5280] 証明書ベースのサーバーおよびクライアント認証をサポートします。PSK 鍵交換が使用される場合(セッション再開など)、PSK の知識がピアの認証に使用されます。
TLS 鍵交換は攻撃者の改ざんに耐性があり、生成される共有秘密は参加するいずれのピアによっても制御できません。
TLS は、QUIC に関心のある2つの基本的なハンドシェイクモードを提供します:
-
完全な 1-RTT ハンドシェイク:クライアントが1往復後にアプリケーションデータを送信でき、サーバーがクライアントの最初のハンドシェイクメッセージを受信した直後に応答します。
-
0-RTT ハンドシェイク:クライアントが、以前にサーバーについて学習した情報を使用してアプリケーションデータを即座に送信します。このアプリケーションデータは攻撃者によって再生される可能性があるため、0-RTT は、再生された場合に望ましくない結果を引き起こす可能性のあるアクションをトリガーする命令を運ぶのには適していません。
図2は、0-RTT アプリケーションデータを含む簡略化された TLS ハンドシェイクを示しています。
クライアント サーバー
ClientHello
(0-RTT アプリケーションデータ) -------->
ServerHello
{EncryptedExtensions}
{Finished}
<-------- [アプリケーションデータ]
{Finished} -------->
[アプリケーションデータ] <-------> [アプリケーションデータ]
() 早期データ (0-RTT) 鍵で保護されたメッセージを示します
{} ハンドシェイク鍵で保護されたメッセージを示します
[] アプリケーションデータ (1-RTT) 鍵で保護されたメッセージを示します
図2: 0-RTT を含む TLS ハンドシェイク
図2では、QUIC で使用されない EndOfEarlyData メッセージが省略されています(セクション 8.3 参照)。同様に、QUIC は ChangeCipherSpec または KeyUpdate メッセージを使用しません。ChangeCipherSpec は TLS 1.3 では冗長です(セクション 8.4 参照)。QUIC には独自の鍵更新メカニズムがあります(セクション6参照)。
データは複数の暗号化レベルを使用して保護されます:
- 初期鍵 (Initial keys)
- 早期データ (0-RTT) 鍵 (Early data (0-RTT) keys)
- ハンドシェイク鍵 (Handshake keys)
- アプリケーションデータ (1-RTT) 鍵 (Application data (1-RTT) keys)
アプリケーションデータは、早期データレベルとアプリケーションデータレベルでのみ表示できます。ハンドシェイクメッセージとアラートメッセージは、どのレベルでも表示できます。
クライアントとサーバーが以前に通信していた場合、0-RTT ハンドシェイクを使用できます。1-RTT ハンドシェイクでは、クライアントはサーバーが送信したすべてのハンドシェイクメッセージを受信するまで、保護されたアプリケーションデータを送信できません。
3. プロトコル概要 (Protocol Overview)
QUIC [QUIC-TRANSPORT] は、パケットの機密性と完全性保護を担当します。そのために、TLS ハンドシェイク [TLS13] から導出された鍵を使用しますが、TCP 上の TLS とは異なり、TLS ハンドシェイクメッセージとアラートメッセージは QUIC トランスポート層によって直接伝送されます。QUIC トランスポート層は、図3に示すように、TLS レコード層の役割を引き継ぎます。
+--------------+--------------+ +-------------+
| TLS | TLS | | QUIC |
| ハンド | アラート | | アプリケー |
| シェイク | | | ション |
| | | | (h3, など) |
+--------------+--------------+-+-------------+
| |
| QUIC トランスポート層 |
| (ストリーム、信頼性、輻輳制御など) |
| |
+---------------------------------------------+
| |
| QUIC パケット保護 |
| |
+---------------------------------------------+
図3: QUIC の階層化
QUIC は、認証と、セキュリティとパフォーマンスの両方にとって重要なパラメータのネゴシエーションについても TLS に依存しています。
これら2つのプロトコルは厳密に階層化されているのではなく、協力して動作します:QUIC は TLS ハンドシェイクを使用し、TLS は QUIC が提供する信頼性、順序付き配信、およびレコード層を使用します。
高レベルでは、TLS コンポーネントと QUIC コンポーネント間には主に2つの相互作用があります:
-
TLS コンポーネントは、QUIC コンポーネントを介してメッセージを送受信します。QUIC は TLS に信頼性のあるストリーム抽象化を提供します。
-
TLS コンポーネントは、QUIC コンポーネントに一連の更新を提供します。これには、(a) インストールする新しいパケット保護鍵、および (b) ハンドシェイク完了、サーバー証明書などの状態変更が含まれます。
図4は、これらの相互作用をより詳細に示しており、QUIC パケット保護が特に指摘されています。
+------------+ +------------+
| |<---- ハンドシェイクメッセージ --->| |
| |<- 0-RTTパラメータの検証 ----->| |
| |<--------- 0-RTT鍵 ----------| |
| QUIC |<------- ハンドシェイク鍵 -----| TLS |
| |<--------- 1-RTT鍵 ----------| |
| |<------- ハンドシェイク完了 ---| |
+------------+ +------------+
| ^
| 保護 | 保護された
v | パケット
+------------+
| QUIC |
| パケット |
| 保護 |
+------------+
図4: QUIC と TLS の相互作用
TCP 上の TLS とは異なり、データの送信を希望する QUIC アプリケーションは、TLS アプリケーションデータレコードを使用してデータを送信しません。代わりに、QUIC STREAM フレームまたは他のフレームタイプとして送信し、その後 QUIC パケットで伝送されます。
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に示すように、さまざまな暗号化鍵とパケット番号空間の関係を示します。
| パケットタイプ | 暗号化鍵 | パケット番号空間 |
|---|---|---|
| Initial | Initial secrets | Initial |
| 0-RTT Protected | 0-RTT | Application data |
| Handshake | Handshake | Handshake |
| Retry | Retry | N/A |
| Version Negotiation | N/A | N/A |
| Short Header | 1-RTT | Application 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)。
5. パケット保護 (Packet Protection)
TCP上のTLSと同様に、QUICはTLSハンドシェイクから派生した鍵を使用してパケットを保護し、TLSによってネゴシエートされたAEADアルゴリズム[AEAD]を使用します。
QUICパケットは、そのタイプに応じて異なる保護を持ちます:
-
バージョンネゴシエーション(Version Negotiation)パケットには暗号化保護がありません。
-
リトライ(Retry)パケットはAEAD_AES_128_GCMを使用して、偶発的な変更に対する保護を提供し、有効なリトライを生成できるエンティティを制限します(セクション5.8を参照)。
-
初期(Initial)パケットはAEAD_AES_128_GCMを使用し、クライアントが送信した最初の初期パケットの宛先接続ID(Destination Connection ID)フィールドから派生した鍵を使用します(セクション5.2を参照)。
-
その他すべてのパケットは、TLSによってネゴシエートされた鍵とアルゴリズムを使用した強力な暗号化機密性と完全性保護を持ちます。
このセクションでは、ハンドシェイク、0-RTT、および1-RTTパケットにパケット保護を適用する方法について説明します。同じパケット保護プロセスが初期パケットに適用されます。ただし、初期パケットに使用される鍵を決定することは簡単であるため、これらのパケットは機密性または完全性保護を持つとは見なされません。リトライパケットは固定鍵を使用するため、機密性と完全性保護も欠いています。
5.1. パケット保護鍵 (Packet Protection Keys)
QUICは、TLSがレコード保護鍵を派生するのと同じ方法でパケット保護鍵を派生します。
各暗号化レベルには、各方向に送信されるパケットを保護するための個別の秘密値があります。これらのトラフィックシークレット(traffic secrets)はTLSによって派生され([TLS13]のセクション7.1を参照)、初期暗号化レベルを除くすべての暗号化レベルでQUICによって使用されます。初期暗号化レベルの秘密は、セクション5.2で説明されているように、クライアントの初期宛先接続IDに基づいて計算されます。
パケット保護に使用される鍵は、TLSが提供するKDFを使用してTLS秘密から計算されます。TLS 1.3では、[TLS13]のセクション7.1で説明されているHKDF-Expand-Label関数が使用され、ネゴシエートされた暗号スイートのハッシュ関数を使用します。QUICにおけるHKDF-Expand-Labelのすべての使用は、長さゼロのコンテキスト(Context)を使用します。
文字列として記述されたラベル(Labels)は、引用符や末尾のNULバイトなしでASCII [ASCII]を使用してバイトにエンコードされることに注意してください。
現在の暗号化レベルの秘密とラベル"quic key"がKDFへの入力として使用され、AEAD鍵を生成します。ラベル"quic iv"は初期化ベクトル(IV)を派生するために使用されます(セクション5.3を参照)。ヘッダー保護鍵はラベル"quic hp"を使用します(セクション5.4を参照)。これらのラベルの使用により、QUICとTLSの間で鍵の分離が提供されます(セクション9.6を参照)。
"quic key"と"quic hp"は両方とも鍵を生成するために使用されるため、これらのラベルでHKDF-Expand-Labelに提供される長さは、AEADまたはヘッダー保護アルゴリズムの鍵サイズによって決定されます。"quic iv"に提供される長さは、最小AEADノンス長、またはそれより大きい場合は8バイトです([AEAD]を参照)。
初期秘密に使用されるKDFは常にTLS 1.3 HKDF-Expand-Label関数です(セクション5.2を参照)。
5.2. 初期シークレット (Initial Secrets)
初期パケットはパケット保護プロセスを適用しますが、クライアントが送信した最初の初期パケットの宛先接続IDフィールドから派生した秘密を使用します。
この秘密はHKDF-Extractを使用して決定されます([HKDF]のセクション2.2を参照)。ソルト(salt)は0x38762cf7f55934b34d179ae6a4c80cadccbb7f0aで、入力鍵材料(IKM)は宛先接続IDフィールドです。これにより、送信と受信の2つの別々の秘密を派生するために使用される中間疑似ランダム鍵(PRK)が生成されます。
クライアントが初期パケットを構築するために使用する秘密は、PRKとラベル"client in"をTLSのHKDF-Expand-Label関数[TLS13]への入力として使用し、32バイトの秘密を生成します。サーバーによって構築されたパケットは、ラベル"server in"を使用して同じプロセスを使用します。初期秘密と鍵の派生のためのHKDFのハッシュ関数はSHA-256 [SHA]です。
このプロセスの疑似コードは次のとおりです:
initial_salt = 0x38762cf7f55934b34d179ae6a4c80cadccbb7f0a
initial_secret = HKDF-Extract(initial_salt,
client_dst_connection_id)
client_initial_secret = HKDF-Expand-Label(initial_secret,
"client in", "",
Hash.length)
server_initial_secret = HKDF-Expand-Label(initial_secret,
"server in", "",
Hash.length)
HKDF-Expand-Labelで使用される接続IDは、クライアントが送信した初期パケットの宛先接続IDです。これは、クライアントがリトライパケットを受信した後に初期パケットを作成する場合を除き、ランダムに選択された値になります。その場合、宛先接続IDはサーバーによって選択されます。
将来のQUICバージョンは新しいソルト値を生成すべきであり(SHOULD)、それによって各QUICバージョンの鍵が異なることを保証します。これにより、1つのQUICバージョンのみを認識するミドルボックスが将来のバージョンのパケット内容を見たり変更したりすることを防ぎます。
初期パケットは、提供されるTLSバージョンにTLS 1.3が含まれていない場合でも、TLS 1.3で定義されているHKDF-Expand-Label関数を使用しなければなりません(MUST)。
サーバーがリトライパケットを送信し、サーバーが選択した接続ID値を使用すると、後続の初期パケットを構築するために使用される秘密が変更されます。サーバーの初期パケットに応答してクライアントが使用する宛先接続IDは秘密を変更しません。
| 注意:宛先接続IDフィールドは最大20バイトの長さ、またはサーバーが長さゼロのソース接続IDフィールドを | 持つリトライパケットを送信した場合は長さゼロである可能性があります。リトライ後、初期鍵はサーバーが | クライアントのパケットを受信したことを保証しないため、クライアントはリトライパケットを含む交換に依存 | してサーバーのアドレスを検証する必要があります([QUIC-TRANSPORT]のセクション8.1を参照)。
付録Aには初期パケットの例が含まれています。
5.3. AEADの使用 (AEAD Usage)
QUICパケット保護に使用される関連データ付き認証暗号化(AEAD)関数([AEAD]を参照)は、TLS接続で使用するためにネゴシエートされたAEADです。たとえば、TLSが暗号スイートTLS_AES_128_GCM_SHA256を使用する場合、AEAD_AES_128_GCM関数が使用されます。
QUICは、TLS_AES_128_CCM_8_SHA256を除き、[TLS13]で定義されている任意の暗号スイートを使用できます。暗号スイートのヘッダー保護スキームが定義されていない限り、暗号スイートをネゴシエートしてはなりません(MUST NOT)。このドキュメントは、TLS_AES_128_CCM_8_SHA256を除き、[TLS13]で定義されているすべての暗号スイートのヘッダー保護スキームを定義します。これらの暗号スイートには16バイトの認証タグがあり、入力より16バイト大きい出力を生成します。
エンドポイントは、サポートしていない暗号スイートを提供するClientHelloを拒否してはなりません(MUST NOT)。そうしないと、新しい暗号スイートを展開できなくなります。これはTLS_AES_128_CCM_8_SHA256にも適用されます。
パケットを構築する際、ヘッダー保護を適用する前にAEAD関数が適用されます(セクション5.4を参照)。保護されていないパケットヘッダーは関連データ(A)の一部です。パケットを処理する際、エンドポイントは最初にヘッダー保護を削除します。
パケット鍵とIVはセクション5.1で説明されているように計算されます。ノンス(N)は、IVをパケット番号と組み合わせることによって形成されます。ネットワークバイトオーダーで再構築された62ビットのQUICパケット番号は、IVのサイズまでゼロで左詰めされます。埋め込まれたパケット番号とIVの排他的論理和(XOR)がAEADノンスを形成します。
AEADの関連データAは、QUICパケットヘッダーの内容で、短いヘッダーまたは長いヘッダーの最初のバイトから始まり、保護されていないパケット番号まで含みます。
AEADの平文Pは、[QUIC-TRANSPORT]で説明されているQUICパケットペイロードです。
AEADの暗号文CはPの代わりに送信されます。
一部のAEAD関数には、同じ鍵とIVで暗号化できるパケット数に制限があります(セクション6.6を参照)。これはパケット番号制限より低い場合があります。エンドポイントは、使用中のAEAD構成によって課される制限を超える前に鍵更新(セクション6)を開始しなければなりません(MUST)。
5.4. ヘッダー保護 (Header Protection)
QUICパケットヘッダーの一部、特にパケット番号フィールドは、パケット保護鍵とIVとは別に派生した鍵を使用して保護されます。ラベル"quic hp"を使用して派生した鍵は、パス上の要素に公開されないフィールドに機密性保護を提供するために使用されます。
この保護は、最初のバイトの最下位ビットとパケット番号フィールドに適用されます。長いヘッダーパケットの場合、最初のバイトの4つの最下位ビットが保護されます。短いヘッダーパケットの場合、最初のバイトの5つの最下位ビットが保護されます。両方のヘッダー形式について、これは予約(Reserved)ビットとパケット番号長(Packet Number Length)フィールドをカバーします。短いヘッダーパケットの鍵フェーズ(Key Phase)ビットも保護されます。
同じヘッダー保護鍵が接続全体に使用され、その値は鍵更新後も変更されません(セクション6を参照)。これにより、ヘッダー保護を使用して鍵フェーズを保護できます。
このプロセスは、保護されたペイロードを含まないか、このプロセスによって保護されるフィールドを含まないリトライまたはバージョンネゴシエーションパケットには適用されません。
注意:ドキュメントの長さを制限し完全性を確保するため、残りのセクション(5.4.1-5.8)の完全な技術詳細については、元のRFC 9001テキストを参照することをお勧めします。これには以下が含まれます:
- 5.4.1. ヘッダー保護の適用
- 5.4.2. ヘッダー保護サンプル
- 5.4.3. AESベースのヘッダー保護
- 5.4.4. ChaCha20ベースのヘッダー保護
- 5.5. 保護されたパケットの受信
- 5.6. 0-RTT鍵の使用
- 5.7. 順不同の保護されたパケットの受信
- 5.8. リトライパケットの完全性
完全な技術ドキュメントについては、次を参照してください:
https://www.rfc-editor.org/rfc/rfc9001.html#section-5
6. 鍵更新 (Key Update)
ハンドシェイクが確認されると(セクション 4.1.2 参照)、エンドポイントは鍵更新を開始してもよいです (MAY)。
鍵フェーズビット (Key Phase bit) は、パケットの保護に使用されるパケット保護鍵を示します。鍵フェーズビットは、最初の 1-RTT パケットのセットでは最初に 0 に設定され、後続の各鍵更新を示すために切り替わります。
鍵フェーズビットにより、受信者は鍵材料の変更を検出できます。変更を含むパケットを受信する必要はありません。鍵フェーズビットの変更に気付いたエンドポイントは、鍵を更新し、変更された値を含むパケットを復号化します。
鍵更新の開始により、両方のエンドポイントが鍵を更新します。これは、エンドポイントが独立して鍵を更新できる TLS とは異なります。
このメカニズムは、KeyUpdate メッセージの送信に依存する TLS の鍵更新メカニズムに代わるものです。KeyUpdate メッセージは 1-RTT 暗号化鍵を使用して送信されます。エンドポイントは TLS KeyUpdate メッセージを送信してはなりません (MUST NOT)。エンドポイントは、TLS KeyUpdate メッセージの受信を、unexpected_message 致命的 TLS アラートに相当する 0x010a タイプの接続エラーとして扱わなければなりません (MUST)(セクション 4.8 参照)。
図9は、鍵更新プロセスを示しています。最初に使用される鍵のセット(@M で識別)が更新された鍵(@N で識別)に置き換えられます。鍵フェーズビットの値は角括弧 [] で示されています。
開始者 応答者
@M [0] QUIC パケット
... @N に更新
@N [1] QUIC パケット
-------->
@N に更新 ...
QUIC パケット [1] @N
<--------
QUIC パケット [1] @N
ACK を含む
<--------
... 鍵更新を許可
@N [1] QUIC パケット
@N パケットへの ACK を含む
-------->
鍵更新を許可 ...
図9: 鍵更新
6.1. 鍵更新の開始 (Initiating a Key Update)
エンドポイントは、パケット保護のために独立した読み取りおよび書き込みシークレットを維持します。エンドポイントは、パケット保護書き込みシークレットを更新し、それを使用して新しいパケットを保護することにより、鍵更新を開始します。エンドポイントは、[TLS13] のセクション 7.2 で説明されているように、既存の書き込みシークレットから新しい書き込みシークレットを作成します。これは、TLS が提供する KDF 関数をラベル "quic ku" で使用します。対応する鍵と IV は、セクション 5.1 で定義されているように、そのシークレットから作成されます。ヘッダー保護鍵は更新されません。
たとえば、TLS 1.3 を使用して書き込み鍵を更新するには、次のように HKDF-Expand-Label を使用します:
secret_<n+1> = HKDF-Expand-Label(secret_<n>, "quic ku",
"", Hash.length)
エンドポイントは鍵フェーズビットの値を切り替え、更新された鍵と IV を使用してすべての後続のパケットを保護します。
エンドポイントは、ハンドシェイクが確認される前に鍵更新を開始してはなりません (MUST NOT)(セクション 4.1.2)。エンドポイントは、現在の鍵フェーズ鍵を使用して保護されたパケットの確認応答を受信していない限り、後続の鍵更新を開始してはなりません (MUST NOT)。これにより、別の鍵更新を開始できるようになる前に、両方のピアで鍵が利用可能であることが保証されます。これは、各鍵フェーズで送信された最低パケット番号と、1-RTT 空間で最高の確認応答パケット番号を追跡することで実現できます。後者が前者以上になると、別の鍵更新を開始できます。
| 注: 1-RTT パケット以外のパケットの鍵は更新されません。それらの鍵は完全に TLS ハンドシェイク状態から派生します。
鍵更新を開始するエンドポイントは、パケットの受信に使用する鍵も更新します。これらの鍵は、ピアが更新後に送信するパケットを処理するために使用されます。
エンドポイントは、新しい鍵を使用して送信されたパケットの保護を正常に解除するまで、古い鍵を保持しなければなりません (MUST)。エンドポイントは、新しい鍵を使用して送信されたパケットの保護を解除した後、一定期間古い鍵を保持すべきです (SHOULD)。古い鍵を早期に破棄すると、遅延パケットが破棄される可能性があります。パケットの破棄は、ピアによってパケット損失として解釈され、パフォーマンスに悪影響を与える可能性があります。
6.2. 鍵更新への応答 (Responding to a Key Update)
ピアは、現在の鍵フェーズのパケットの確認応答を受信した後、鍵更新を開始できます。エンドポイントは、鍵フェーズが最後に送信したパケットで使用された値と異なるパケットを処理するときに、鍵更新を検出します。このパケットを処理するために、エンドポイントは次のパケット保護鍵と IV を使用します。これらの鍵の生成に関する考慮事項については、セクション 6.3 を参照してください。
パケットが次の鍵と IV を使用して正常に処理された場合、ピアは鍵更新を開始しました。エンドポイントは、セクション 6.1 で説明されているように、送信鍵を対応する鍵フェーズに更新しなければなりません (MUST)。更新された鍵を使用して受信したパケットの確認応答を送信する前に、送信鍵を更新しなければなりません (MUST)。更新された鍵で保護されたパケットで鍵更新をトリガーしたパケットを確認することにより、エンドポイントは鍵更新が完了したことを示します。
エンドポイントは、通常のパケット送信動作に従って、パケットまたは確認応答の送信を延期してもよいです (MAY)。鍵更新に応答するために即座にパケットを生成する必要はありません。エンドポイントが送信する次のパケットは、更新された鍵を使用します。確認応答を含む次のパケットにより、鍵更新が完了します。鍵更新を開始したパケットの確認応答を含む更新鍵パケットを送信する前に、エンドポイントが2回目の更新を検出した場合、これはピアが確認応答を待たずに2回鍵を更新したことを示しています。エンドポイントは、このような連続した鍵更新を KEY_UPDATE_ERROR タイプの接続エラーとして扱ってもよいです (MAY)。
エンドポイントが、古い鍵で保護されたパケットで運ばれる確認応答を受信し、確認応答されたパケットのいずれかが新しい鍵で保護されている場合、それを KEY_UPDATE_ERROR タイプの接続エラーとして扱ってもよいです (MAY)。これは、ピアが鍵更新を開始したパケットを受信して確認応答したが、応答として鍵を更新しなかったことを示しています。
6.3. 受信鍵生成のタイミング (Timing of Receive Key Generation)
明らかな鍵更新に応答するエンドポイントは、鍵フェーズビットが無効であることを示す可能性のあるタイミングサイドチャネル信号を生成してはなりません (MUST NOT)(セクション 9.5 参照)。鍵更新がまだ許可されていない場合、エンドポイントは、破棄された鍵の代わりにランダムなパケット保護鍵を使用できます。ランダム鍵を使用すると、パケット保護を解除しようとする試みがタイミングの変化を引き起こさず、無効な鍵フェーズビットを持つパケットが拒否されることが保証されます。
パケットを受信するための新しいパケット保護鍵を作成するプロセスは、鍵更新が発生したことを明らかにする可能性があります。エンドポイントは、パケット処理の一環として新しい鍵を生成してもよいですが (MAY)、これによりタイミング信号が作成され、攻撃者はそれを利用して鍵更新がいつ発生したかを知り、鍵フェーズビットの値を漏洩させることができます。
エンドポイントは通常、現在および次の受信パケット保護鍵を持つべきです。鍵更新が完了してから PTO まで短時間の間、エンドポイントは次のセットの受信パケット保護鍵の生成を延期してもよいです (MAY)。これにより、エンドポイントは2セットの受信鍵のみを保持できます(セクション 6.5 参照)。
生成されると、次のセットのパケット保護鍵は保持すべきであり (SHOULD)、受信したパケットがその後破棄されても同様です。明らかな鍵更新を含むパケットは簡単に偽造できますが、鍵更新プロセスには大きな労力を必要としませんが、このプロセスをトリガーすることは攻撃者によって DoS に使用される可能性があります。
したがって、エンドポイントは、パケットを受信するための2セットのパケット保護鍵(現在の鍵と次の鍵)を保持できなければなりません (MUST)。これらの鍵に加えて、以前の鍵を保持するとパフォーマンスが向上する可能性がありますが、これは必須ではありません。
6.4. 更新された鍵での送信 (Sending with Updated Keys)
エンドポイントは、古い鍵で保護されたパケットを送信しません。現在の鍵のみを使用します。パケットの保護に使用される鍵は、新しい鍵に切り替えた後すぐに破棄できます。
より高いパケット番号を持つパケットは、より低いパケット番号を持つパケットと同じかそれより新しいパケット保護鍵を使用して保護されなければなりません (MUST)。エンドポイントが、より低いパケット番号を持つパケットに新しい鍵が使用されていることを検出した場合、古い鍵を使用して保護を正常に解除すると、これを KEY_UPDATE_ERROR タイプの接続エラーとして扱わなければなりません (MUST)。
6.5. 異なる鍵での受信 (Receiving with Different Keys)
鍵更新中にパケットを受信すると、古い鍵で保護されたパケットがネットワークで遅延している場合、それらが到着する可能性があります。古いパケット保護鍵を保持することで、これらのパケットを正常に処理できます。
次の鍵フェーズ鍵で保護されたパケットは、前の鍵フェーズ鍵で保護されたパケットと同じ鍵フェーズ値を使用するため、古い鍵で保護されたパケットを処理する必要がある場合は、2つを区別する必要があります。これはパケット番号によって行うことができます。復元されたパケット番号が現在の鍵フェーズのパケット番号より低い場合は、前のパケット保護鍵を使用します。復元されたパケット番号が現在の鍵フェーズのパケット番号より高い場合は、次のパケット保護鍵を使用する必要があります。
前の、現在、および次のパケット保護鍵を選択する任意のプロセスが、パケット保護の解除に使用された鍵を明らかにする可能性のあるタイミングサイドチャネルを公開しないように注意する必要があります。詳細については、セクション 9.5 を参照してください。
あるいは、エンドポイントは2セットのパケット保護鍵のみを保持し、ネットワークで順序が乱れた十分な時間が経過した後、前の鍵を次の鍵に置き換えることができます。この場合、鍵フェーズビットのみを使用して鍵を選択できます。
エンドポイントは、次のセットの受信鍵を現在の鍵に昇格させた後、約1プローブタイムアウト (PTO)([QUIC-RECOVERY] 参照)を許可してから、後続のパケット保護鍵のセットを作成してもよいです (MAY)。これらの更新された鍵は、その時点で以前の鍵を置き換えてもよいです (MAY)。PTO は主観的な測定であり、ピアは RTT について異なる見解を持つ可能性があることに注意してください。この期間は、確認応答されても順序が乱れたパケットがピアによって損失として宣言されるほど長く、ピアがさらなる鍵更新を開始できるほど短いことが期待されます。
エンドポイントは、古い鍵を保持している期間中、ピアが鍵更新を開始したパケットを復号化できない可能性を考慮する必要があります。エンドポイントは、以前の鍵更新を確認応答する確認応答を受信した後、3倍の PTO を待ってから鍵更新を開始すべきです (SHOULD)。十分な時間を残さないと、パケットが破棄される可能性があります。
エンドポイントは、新しい鍵を使用して保護されたパケットを受信した後、3倍の PTO を超えて古い読み取り鍵を保持すべきではありません (SHOULD)。この期間の後、古い読み取り鍵とそれに対応するシークレットは破棄すべきです (SHOULD)。
6.6. AEAD 使用の制限 (Limits on AEAD Usage)
本文書は、QUIC で使用する際に過度の使用が攻撃者に通信の機密性と完全性を攻撃する上で不均衡な利点を与えないようにするために、AEAD アルゴリズムの使用制限を設定します。
TLS 1.3 で定義された使用制限は、機密性への攻撃を防ぐためのものであり、AEAD 保護の適用成功に適用されます。認証暗号化における完全性保護は、パケットの偽造試行の制限にも依存しています。TLS は、認証チェックに失敗したレコードの後に接続を閉じることでこれを実現します。対照的に、QUIC は認証できないパケットを無視し、複数の偽造試行を許可します。
QUIC は、AEAD の機密性と完全性の制限を個別に考慮します。機密性制限は、特定の鍵を使用して暗号化されたパケット数に適用されます。完全性制限は、特定の接続で復号化されたパケット数に適用されます。以下では、各 AEAD アルゴリズムのこれらの制限の実施について詳しく説明します。
エンドポイントは、各鍵セットの暗号化されたパケット数をカウントしなければなりません (MUST)。同じ鍵を使用して暗号化されたパケットの総数が、選択した AEAD の機密性制限を超える場合、エンドポイントはこれらの鍵の使用を停止しなければなりません (MUST)。エンドポイントは、選択した AEAD に許可された機密性制限を超える保護されたパケットを送信する前に、鍵更新を開始しなければなりません (MUST)。鍵更新ができない場合、または完全性制限に達した場合、エンドポイントは接続の使用を停止し、パケットを受信したときにのみステートレスリセットを送信しなければなりません (MUST)。エンドポイントは、鍵更新が不可能な状態に達する前に、AEAD_LIMIT_REACHED タイプの接続エラーを使用して接続を即座に閉じることが推奨されます (RECOMMENDED)。
AEAD_AES_128_GCM および AEAD_AES_256_GCM の場合、機密性制限は 2^23 暗号化パケットです(付録 B.1 参照)。AEAD_CHACHA20_POLY1305 の場合、機密性制限は可能なパケット数 (2^62) よりも大きいため、無視できます。AEAD_AES_128_CCM の場合、機密性制限は 2^21.5 暗号化パケットです(付録 B.2 参照)。制限を適用すると、攻撃者が使用された AEAD をランダム順列と区別できる確率が低下します([AEBounds]、[ROBUST]、[GCM-MU] 参照)。
送信されたパケットのカウントに加えて、エンドポイントは、接続の生存期間中に認証に失敗した受信パケットの数をカウントしなければなりません (MUST)。すべての鍵にわたる接続で認証に失敗した受信パケットの総数が、選択した AEAD の完全性制限を超える場合、エンドポイントは AEAD_LIMIT_REACHED タイプの接続エラーを使用して接続を即座に閉じ、パケットを処理しなくなる必要があります (MUST)。
AEAD_AES_128_GCM および AEAD_AES_256_GCM の場合、完全性制限は 2^52 無効パケットです(付録 B.1 参照)。AEAD_CHACHA20_POLY1305 の場合、完全性制限は 2^36 無効パケットです([AEBounds] 参照)。AEAD_AES_128_CCM の場合、完全性制限は 2^21.5 無効パケットです(付録 B.2 参照)。この制限を適用すると、攻撃者がパケットの偽造に成功する確率が低下します([AEBounds]、[ROBUST]、[GCM-MU] 参照)。
パケットサイズを制限するエンドポイントは、より高い機密性と完全性の制限を使用してもよいです (MAY)。詳細については付録 B を参照してください。
将来の分析と仕様により、AEAD の機密性または完全性の制限が緩和される可能性があります (MAY)。
QUIC で使用するように指定された TLS 暗号スイートは、機密性と完全性のマージンを維持するために、関連する AEAD 関数の使用制限を定義しなければなりません (MUST)。つまり、認証できるパケット数と認証に失敗できるパケット数の制限を指定しなければなりません (MUST)。値ベースの分析への参照(およびその分析で使用される仮定)を提供することで、異なる使用条件に基づいて制限を調整できます。
6.7. 鍵更新エラーコード (Key Update Error Code)
KEY_UPDATE_ERROR エラーコード (0x0e) は、鍵更新に関連するエラーに使用されます。
7. 初期メッセージのセキュリティ (Security of Initial Messages)
Initial パケットは秘密鍵で保護されていないため、攻撃者による改ざんの対象となる可能性があります。QUIC は、パケットを読み取れない攻撃者に対する保護を提供しますが、攻撃者がパケットを観察して注入できる攻撃に対する追加の保護を提供しようとはしません。一部の形式の改ざん(TLS メッセージ自体の変更など)は検出可能ですが、一部(ACK の変更など)は検出できません。
たとえば、攻撃者は ACK フレームを含むパケットを注入して、パケットが受信されなかったように見せかけたり、接続状態の誤った印象を作成したりできます(ACK 遅延を変更するなど)。このようなパケットは、正当なパケットが重複パケットとして破棄される原因となる可能性があることに注意してください。実装は、Initial パケットに含まれる検証されていないデータに依存する際に注意すべきです (SHOULD)。
攻撃者は Handshake パケットで運ばれるデータも改ざんする可能性がありますが、このような改ざんには TLS ハンドシェイクメッセージの変更が必要であるため、このような改ざんは TLS ハンドシェイクの失敗につながります。
8. TLSハンドシェイクへのQUIC固有の調整 (QUIC-Specific Adjustments to the TLS Handshake)
QUICと共に使用される場合、TLSハンドシェイクのいくつかの側面が異なります。
QUICはまた、暗号化ハンドシェイクがセキュリティとパフォーマンスの両方にとって重要なパラメータの認証されたネゴシエーションを提供することを要求します。暗号化パラメータのネゴシエーションに加えて、TLSハンドシェイクはQUICトランスポートパラメータの値も転送および検証します。
8.1. プロトコルネゴシエーション (Protocol Negotiation)
QUICは、暗号化ハンドシェイクがプロトコルネゴシエーションの認証を提供することを要求します。TLSはアプリケーション層プロトコルネゴシエーション(ALPN)[ALPN]を使用してアプリケーションプロトコルを選択します。アプリケーションプロトコルを合意するために別のメカニズムが使用されない限り、エンドポイントはこの目的でALPNを使用しなければなりません(MUST)。
ALPNを使用する場合、アプリケーションプロトコルがネゴシエートされない場合、エンドポイントはno_application_protocol TLSアラート(QUICエラーコード0x0178;セクション4.8を参照)を使用して直ちに接続を閉じなければなりません(MUST)([QUIC-TRANSPORT]のセクション10.2を参照)。[ALPN]は、このアラートを使用するのはサーバーのみであると指定していますが、QUICクライアントはALPNネゴシエーションが失敗したときに接続を終了するためにエラー0x0178を使用しなければなりません(MUST)。
アプリケーションプロトコルは、使用できるQUICバージョンを制限することができます(MAY)。サーバーは、クライアントが選択したQUICバージョンと互換性のあるアプリケーションプロトコルを選択しなければなりません(MUST)。サーバーは、互換性のあるアプリケーションプロトコルを選択できない場合を、タイプ0x0178(no_application_protocol)の接続エラーとして扱わなければなりません(MUST)。同様に、クライアントは、サーバーが互換性のないアプリケーションプロトコルを選択した場合を、タイプ0x0178の接続エラーとして扱わなければなりません(MUST)。
8.2. QUICトランスポートパラメータ拡張 (QUIC Transport Parameters Extension)
QUICトランスポートパラメータはTLS拡張で転送されます。QUICの異なるバージョンは、トランスポート構成をネゴシエートするための異なる方法を定義する可能性があります。
TLSハンドシェイクにトランスポートパラメータを含めることで、これらの値の完全性保護が提供されます。
enum {
quic_transport_parameters(0x39), (65535)
} ExtensionType;
quic_transport_parameters拡張のextension_dataフィールドには、使用されているQUICバージョンによって定義された値が含まれます。
quic_transport_parameters拡張は、ハンドシェイク中のClientHelloおよびEncryptedExtensionsメッセージで転送されます。エンドポイントはquic_transport_parameters拡張を送信しなければなりません(MUST)。quic_transport_parameters拡張のないClientHelloまたはEncryptedExtensionsを受信したエンドポイントは、タイプ0x016dのエラーで接続を閉じなければなりません(MUST)(TLS致命的アラートmissing_extensionと同等;セクション4.8を参照)。
トランスポートパラメータは、ハンドシェイクが完了する前に利用可能になります。サーバーは、ハンドシェイクが完了する前にこれらの値を使用できます。ただし、ハンドシェイクが完了するまでトランスポートパラメータ値は認証されないため、これらのパラメータの使用はその真正性に依存できません。トランスポートパラメータの改ざんはハンドシェイクの失敗につながります。
エンドポイントは、QUICを使用しないTLS接続([TLS13]で定義されているTCP上のTLSの使用など)でこの拡張を送信してはなりません(MUST NOT)。この拡張をサポートする実装は、トランスポートがQUICでない場合にこの拡張を受信したときに、unsupported_extension致命的アラートを送信しなければなりません(MUST)。
quic_transport_parameters拡張のネゴシエーションにより、EndOfEarlyDataが削除されます(セクション8.3を参照)。
8.3. EndOfEarlyDataメッセージの削除 (Removing the EndOfEarlyData Message)
TLS EndOfEarlyDataメッセージはQUICで使用されません。QUICは、0-RTTデータの終了をマークしたり、ハンドシェイク鍵への切り替えを通知したりするためにこのメッセージに依存しません。
クライアントはEndOfEarlyDataメッセージを送信してはなりません(MUST NOT)。サーバーは、0-RTTデータパケットでCRYPTOフレームを受信した場合を、タイプPROTOCOL_VIOLATIONの接続エラーとして扱わなければなりません(MUST)。
その結果、EndOfEarlyDataはTLSハンドシェイクトランスクリプトに表示されません。
8.4. TLSミドルボックス互換モードの禁止 (Prohibiting TLS Middlebox Compatibility Mode)
[TLS13]の付録D.4は、一部のミドルボックスのバグに対する回避策として、TLS 1.3ハンドシェイクへの変更について説明しています。TLS 1.3ミドルボックス互換モードには、ClientHelloとServerHelloのlegacy_session_idフィールドを32バイトの値に設定し、change_cipher_specレコードを送信することが含まれます。フィールドもレコードもセマンティックコンテンツを持たず、無視されます。
このモードは、TCP上のTLSに干渉するミドルボックスにのみ適用されるため、QUICでは役に立ちません。QUICはchange_cipher_specレコードを転送する手段さえ提供しません。クライアントはTLS 1.3互換モードの使用を要求してはなりません(MUST NOT)。サーバーは、空でないlegacy_session_idフィールドを持つTLS ClientHelloの受信を、タイプPROTOCOL_VIOLATIONの接続エラーとして扱うべきです(SHOULD)。
9. セキュリティに関する考察 (Security Considerations)
TLS に適用されるすべてのセキュリティに関する考察は、QUIC での TLS の使用にも適用されます。[TLS13] とその付録のすべてを読むことが、QUIC のセキュリティ特性を理解するための最良の方法です。
本セクションでは、TLS 統合に固有のより重要なセキュリティ側面のいくつかを要約していますが、文書の残りの部分には多くのセキュリティ関連の詳細があります。
9.1. セッションリンク可能性 (Session Linkability)
TLS セッションチケットの使用により、サーバーおよび場合によっては他のエンティティが、同じクライアントによって確立された接続を関連付けることができます。詳細については、セクション 4.5 を参照してください。
9.2. 0-RTT でのリプレイ攻撃 (Replay Attacks with 0-RTT)
[TLS13] のセクション8で説明されているように、TLS 早期データの使用はリプレイ攻撃にさらされます。QUIC での 0-RTT の使用も同様にリプレイ攻撃に脆弱です。
エンドポイントは [TLS13] で説明されているリプレイ保護を実装して使用しなければなりません (MUST)。ただし、これらの保護は不完全であることが認識されています。したがって、リプレイのリスクに関する追加の考慮が必要です。
QUIC は、運ぶ可能性のあるアプリケーションプロトコル情報を介する場合を除き、リプレイ攻撃に脆弱ではありません。[QUIC-TRANSPORT] で定義されたフレームタイプに基づく QUIC プロトコル状態の管理は、リプレイに脆弱ではありません。QUIC フレームの処理はべき等であり、フレームがリプレイ、再配列、または損失した場合でも、無効な接続状態になることはありません。QUIC 接続は、QUIC が提供するアプリケーションプロトコルによって生成されるものを除いて、接続の存続期間を超えて持続する影響を生成しません。
TLS セッションチケットとアドレス検証トークンは、接続間で QUIC 構成情報を運ぶために使用され、特にサーバーが接続確立とアドレス検証で使用される状態を効率的に復元できるようにします。これらは、エンドポイント間でアプリケーションセマンティクスを通信するために使用してはなりません (MUST NOT)。クライアントはこれらを不透明な値として扱わなければなりません (MUST)。これらのトークンの再利用の可能性は、リプレイに対してより強力な保護が必要であることを意味します。
接続で 0-RTT を受け入れるサーバーは、0-RTT なしで接続を受け入れるよりも高いコストを負担します。これには、より高い処理と計算コストが含まれます。サーバーは、0-RTT を受け入れるときに、リプレイの確率とすべての関連コストを考慮する必要があります。
最終的に、0-RTT でのリプレイ攻撃のリスクを管理する責任は、アプリケーションプロトコルにあります。QUIC を使用するアプリケーションプロトコルは、プロトコルが 0-RTT を使用する方法と、リプレイ攻撃から保護するために採用される措置を記述しなければなりません (MUST)。リプレイリスクの分析では、アプリケーションセマンティクスを運ぶすべての QUIC プロトコル機能を考慮する必要があります。
0-RTT を完全に無効にすることは、リプレイ攻撃に対する最も効果的な防御です。
QUIC 拡張は、リプレイ攻撃がその操作にどのように影響するかを説明するか、0-RTT での拡張の使用を禁止しなければなりません (MUST)。アプリケーションプロトコルは、0-RTT でアプリケーションセマンティクスを運ぶ拡張の使用を禁止するか、リプレイ軽減戦略を提供しなければなりません (MUST)。
9.3. パケット反射攻撃の軽減 (Packet Reflection Attack Mitigation)
サーバーからの大きなハンドシェイクメッセージブロックを生成する小さな ClientHello は、パケット反射攻撃で攻撃者が生成するトラフィックを増幅するために使用できます。
QUIC には、この攻撃に対する3つの防御があります。第一に、ClientHello を含むパケットは最小サイズまでパディングされなければなりません (MUST)。第二に、未検証のソースアドレスに応答する場合、サーバーは受信したバイト数の3倍を超えるバイトを送信することが禁止されています([QUIC-TRANSPORT] のセクション 8.1 参照)。最後に、Handshake パケットの確認応答は認証されるため、ブラインド攻撃者はそれらを偽造できません。これらの防御を組み合わせることで、増幅のレベルが制限されます。
9.4. ヘッダー保護分析 (Header Protection Analysis)
[NAN] は、ノンスプライバシーを提供する認証暗号化アルゴリズムを分析し、「Hide Nonce (HN)」変換と呼ばれています。本文書の一般的なヘッダー保護構造は、これらのアルゴリズムの1つ (HN1) です。ヘッダー保護は、パケット保護 AEAD の後に適用され、AEAD 出力から一連のバイト(「サンプル」)をサンプリングし、次のように疑似ランダム関数 (PRF) を使用してヘッダーフィールドを暗号化します:
protected_field = field XOR PRF(hp_key, sample)
本文書のヘッダー保護バリアントは、一般的な PRF の代わりに疑似ランダム順列 (PRP) を使用します。ただし、すべての PRP も PRF であるため [IMC]、これらのバリアントは HN1 構造から逸脱しません。
"hp_key" がパケット保護鍵とは異なるため、ヘッダー保護は [NAN] で定義された AE2 セキュリティを達成し、したがって保護されたパケットヘッダーである "field" のプライバシーを保証します。この構造に基づく将来のヘッダー保護バリアントは、同等のセキュリティ保証を確保するために PRF を使用しなければなりません (MUST)。
同じ鍵と暗号文サンプルを複数回使用すると、ヘッダー保護が侵害されるリスクがあります。同じ鍵と暗号文サンプルで2つの異なるヘッダーを保護すると、保護されたフィールドの排他的論理和が明らかになります。AEAD が PRF として機能すると仮定すると、L ビットがサンプリングされる場合、2つの暗号文サンプルが同一である確率は 2^(-L/2) に近づきます。つまり、誕生日境界です。本文書で説明されているアルゴリズムの場合、その確率は 2^64 分の1です。
攻撃者がパケットヘッダーを変更するのを防ぐため、ヘッダーはパケット保護を使用して推移的に認証されます。パケットヘッダー全体が認証された関連データの一部です。偽造または変更された保護されたフィールドは、パケット保護が削除された後にのみ検出できます。
9.5. ヘッダー保護タイミングサイドチャネル (Header Protection Timing Side Channels)
攻撃者は、パケット番号や鍵フェーズの値を推測し、タイミングサイドチャネルを通じてエンドポイントに推測を確認させることができます。同様に、パケット番号長の推測を試みて公開できます。パケットの受信者が、パケット保護を削除しようとせずに重複したパケット番号を持つパケットを破棄する場合、タイミングサイドチャネルを通じてパケット番号が受信したパケットと一致することを明らかにする可能性があります。認証がサイドチャネルから解放されるためには、ヘッダー保護の削除、パケット番号の回復、およびパケット保護の削除のプロセス全体を、タイミングやその他のサイドチャネルなしで一緒に適用しなければなりません (MUST)。
パケットの送信については、パケットペイロードとパケット番号の構築と保護は、パケット番号またはそのエンコードされたサイズを明らかにするサイドチャネルから解放されなければなりません (MUST)。
鍵更新中、新しい鍵を生成するのにかかる時間により、タイミングサイドチャネルを通じて鍵更新が発生したことが明らかになる可能性があります。あるいは、攻撃者がパケットを注入する場合、このサイドチャネルは注入されたパケットの鍵フェーズの値を明らかにする可能性があります。鍵更新を受信した後、エンドポイントは、セクション 6.3 で説明されているように、次のセットの受信パケット保護鍵を生成して保存すべきです (SHOULD)。鍵更新を受信する前に新しい鍵を生成することにより、パケットの受信は鍵フェーズの値を漏洩するタイミング信号を作成しません。
これは、パケット処理中にこの鍵生成を行わないことに依存しており、エンドポイントが受信のために3セットのパケット保護鍵を維持することを要求する場合があります:前の鍵フェーズ用、現在の鍵フェーズ用、および次の鍵フェーズ用。代わりに、エンドポイントは、古い鍵を破棄するまで次の受信パケット保護鍵の生成を延期することを選択でき、その結果、いつでも2セットの受信鍵のみを保持する必要があります。
9.6. 鍵の多様性 (Key Diversity)
TLS を使用する場合、TLS の中央鍵スケジュールが使用されます。TLS ハンドシェイクメッセージが秘密の計算に統合された結果、QUIC トランスポートパラメータ拡張を含めることで、ハンドシェイクおよび 1-RTT 鍵が TCP 上で TLS を実行するサーバーによって生成される可能性のある鍵とは異なることが保証されます。クロスプロトコル鍵同期の可能性を回避するために、鍵分離を改善するための追加措置が提供されます。
QUIC パケット保護鍵と IV は、TLS の同等の鍵とは異なるラベルを使用して派生されます。
この分離を維持するために、QUIC の新しいバージョンでは、パケット保護鍵と IV、およびヘッダー保護鍵の鍵派生に新しいラベルを定義すべきです (SHOULD)。このバージョンの QUIC は文字列 "quic" を使用します。他のバージョンは、その文字列の代わりにバージョン固有のラベルを使用できます。
初期シークレットは、ネゴシエートされた QUIC バージョンに固有の鍵を使用します。新しい QUIC バージョンでは、初期シークレットの計算に使用される新しいソルト値を定義すべきです (SHOULD)。
9.7. ランダム性 (Randomness)
QUIC は、接続 ID などのプロトコル値に直接、および TLS を介して推移的に、エンドポイントが安全な乱数を生成できることに依存しています。安全な乱数生成のガイダンスについては、[RFC4086] を参照してください。
10. IANA に関する考察 (IANA Considerations)
IANA は、"TLS ExtensionType Values" レジストリ [TLS-REGISTRIES] に、quic_transport_parameters 拡張(セクション 8.2 で定義)のコードポイント 57 (または 0x39) を登録しました。
この拡張の Recommended 列は Yes とマークされています。TLS 1.3 列には CH (ClientHello) と EE (EncryptedExtensions) が含まれます。
| 値 | 拡張名 | TLS 1.3 | 推奨 | 参照 |
|---|---|---|---|---|
| 57 | quic_transport_parameters | CH, EE | Y | 本文書 |
表2: TLS ExtensionType Values レジストリエントリ
11. 参考文献 (References)
11.1. 規範的参考文献 (Normative References)
本セクションには、RFC 9001 で参照されている規範的文献が含まれます。完全なリストについては、英語版の原文を参照してください。
主要な参考文献:
- [TLS13] - RFC 8446: The Transport Layer Security (TLS) Protocol Version 1.3
- [QUIC-TRANSPORT] - RFC 9000: QUIC: A UDP-Based Multiplexed and Secure Transport
- [QUIC-RECOVERY] - RFC 9002: QUIC Loss Detection and Congestion Control
- [RFC2119] - RFC 2119: Key words for use in RFCs to Indicate Requirement Levels
- [RFC8174] - RFC 8174: Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words
11.2. 参考情報 (Informative References)
本セクションには、RFC 9001 で参照されている参考情報が含まれます。
主要な参考文献:
- [AEBounds] - Limits on Authenticated Encryption Use in TLS
- [ALPN] - RFC 7301: Transport Layer Security (TLS) Application-Layer Protocol Negotiation Extension
- [QUIC-HTTP] - RFC 9114: HTTP/3
- [NAN] - Nonces Are Noticed: AEAD Revisited
完全な参考文献リストについては、公式の RFC 9001 原文を参照してください: https://www.rfc-editor.org/rfc/rfc9001.html
付録 A. パケット保護のサンプル (Sample Packet Protection)
本セクションでは、実装を段階的に検証できるように、パケット保護の例を示します。クライアントとサーバーからの Initial パケットのサンプルと、Retry パケットが定義されています。これらのパケットは、8バイトのクライアント選択の宛先接続 ID 0x8394c8f03e515708 を使用します。いくつかの中間値が含まれています。すべての値は16進数で示されています。
A.1. 鍵 (Keys)
HKDF-Expand-Label 関数の実行中に生成されるラベル(つまり、HkdfLabel.label)と、出力を生成するために HKDF-Expand 関数に提供される値の一部は次のとおりです:
client in: 00200f746c73313320636c69656e7420696e00
server in: 00200f746c7331332073657276657220696e00
quic key: 00100e746c7331332071756963206b657900
quic iv: 000c0d746c733133207175696320697600
quic hp: 00100d746c733133207175696320687000
初期シークレットは共通です:
initial_secret = HKDF-Extract(initial_salt, cid)
= 7db5df06e7a69e432496adedb0085192
3595221596ae2ae9fb8115c1e9ed0a44
クライアントパケットを保護するための鍵:
client_initial_secret
= HKDF-Expand-Label(initial_secret, "client in", "", 32)
= c00cf151ca5be075ed0ebfb5c80323c4
2d6b7db67881289af4008f1f6c357aea
key = HKDF-Expand-Label(client_initial_secret, "quic key", "", 16)
= 1f369613dd76d5467730efcbe3b1a22d
iv = HKDF-Expand-Label(client_initial_secret, "quic iv", "", 12)
= fa044b2f42a3fd3b46fb255c
hp = HKDF-Expand-Label(client_initial_secret, "quic hp", "", 16)
= 9f50449e04a0e810283a1e9933adedd2
サーバーパケットを保護するための鍵:
server_initial_secret
= HKDF-Expand-Label(initial_secret, "server in", "", 32)
= 3c199828fd139efd216c155ad844cc81
fb82fa8d7446fa7d78be803acdda951b
key = HKDF-Expand-Label(server_initial_secret, "quic key", "", 16)
= cf3a5331653c364c88f0f379b6067e37
iv = HKDF-Expand-Label(server_initial_secret, "quic iv", "", 12)
= 0ac1493ca1905853b0bba03e
hp = HKDF-Expand-Label(server_initial_secret, "quic hp", "", 16)
= c206b8d9b9f0f37644430b490eeaa314
A.2. クライアント Initial パケット
クライアントは Initial パケットを送信します。このパケットの保護されていないペイロードには、以下の CRYPTO フレームと、1162バイトのペイロードを作成するのに十分な PADDING フレームが含まれています。
(16進数データは省略 - 原文参照)
保護されていないヘッダーは1182バイトの長さを示します:4バイトのパケット番号、1162バイトのフレーム、および16バイトの認証タグ。ヘッダーには接続 ID とパケット番号2が含まれています。
ペイロードを保護すると、ヘッダー保護のためにサンプリングされる出力が生成されます。ヘッダーは4バイトのパケット番号エンコーディングを使用するため、保護されたペイロードの最初の16バイトがサンプリングされ、次のようにヘッダーに適用されます:
sample = d1b1c98dd7689fb8ec11d242b123dc9b
mask = AES-ECB(hp, sample)[0..4] = 437b9aec36
header[0] ^= mask[0] & 0x0f = c0
header[18..21] ^= mask[1..4] = 7b9aec34
header = c000000001088394c8f03e5157080000449e7b9aec34
(完全な保護されたパケットは省略 - 原文参照)
A.3. サーバー Initial パケット
サーバーは、ACK フレーム、CRYPTO フレームを含み、PADDING フレームを含まない以下のペイロードを応答として送信します。
(詳細は省略 - 原文参照)
A.4. Retry パケット
付録 A.2 の Initial パケットへの応答として送信される可能性のある Retry パケットを示します。完全性チェックには、クライアントが選択した接続 ID 値 0x8394c8f03e515708 が含まれますが、その値は最終的な Retry パケットには含まれません。
ff000000010008f067a5502a4262b574 6f6b656e04a265ba2eff4d829058fb3f
0f2496ba
A.5. ChaCha20-Poly1305 短ヘッダーパケット
この例は、短ヘッダーでパケットを保護するために必要ないくつかのステップを示しています。この例では AEAD_CHACHA20_POLY1305 を使用します。
(詳細な鍵導出とパケット保護の手順は省略 - 原文参照)
保護されたパケットは21バイトの最小可能パケットサイズです:
packet = 4cfe4189655e5cd55c41f69080575d7999c25a5bfb
付録 B. AEAD アルゴリズム解析 (AEAD Algorithm Analysis)
本セクションでは、AEAD_AES_128_GCM、AEAD_AES_128_CCM、および AEAD_AES_256_GCM の AEAD アルゴリズム制限を導出するために使用される解析を文書化します。
以下の記号が使用されます:
t: 認証タグのサイズ(ビット単位)。これらの暗号では、t は 128 です。
n: ブロック関数のサイズ(ビット単位)。これらの暗号では、n は 128 です。
k: 鍵のサイズ(ビット単位)。AEAD_AES_128_GCM および AEAD_AES_128_CCM では 128、AEAD_AES_256_GCM では 256 です。
l: 各パケットのブロック数。
q: エンドポイントが作成および保護する真正なパケットの数。この値は、鍵を更新する前に保護できるパケット数の境界です。
v: エンドポイントが受け入れる偽造パケットの数。この値は、鍵を更新する前にエンドポイントが拒否できる偽造パケット数の境界です。
o: 攻撃者が行うオフライン理想暗号クエリの量。
B.1. AEAD_AES_128_GCM および AEAD_AES_256_GCM の使用制限の解析
[GCM-MU] は、TLS 1.3 および QUIC で使用される AEAD_AES_128_GCM および AEAD_AES_256_GCM の具体的な境界を指定します。本セクションでは、いくつかの簡略化された仮定を使用してこの解析を文書化します。
B.1.1. 機密性制限 (Confidentiality Limit)
機密性について、[GCM-MU] の定理 (4.3) は、ノンスを繰り返さない単一ユーザーの場合、攻撃者が実際の AEAD アルゴリズムとランダム AEAD アルゴリズムの間で得る識別優位性の支配項が次のとおりであることを確立します:
2 * (q * l)^2 / 2^n
2^-57 の目標優位性の場合、これは次の関係になります:
q <= 2^35 / l
したがって、2^11 バイトより大きいパケットを送信しないエンドポイントは、攻撃者が 2^-57 の目標よりも大きな優位性を得ることなく、単一の接続で 2^28 を超えるパケットを保護できません。2^16 までのパケットサイズを許可するエンドポイントの制限は、代わりに 2^23 です。
B.1.2. 完全性制限 (Integrity Limit)
完全性について、[GCM-MU] の定理 (4.3) は、攻撃者がパケットの偽造に成功する優位性が次を超えないことを確立します:
(1 / 2^(8 * n)) + ((2 * v) / 2^(2 * n))
+ ((2 * o * v) / 2^(k + n)) + (n * (v + (v * l)) / 2^k)
目標は、この優位性を 2^-57 に制限することです。AEAD_AES_128_GCM の場合、この不等式の第4項が他を支配するため、結果に大きな影響を与えずに他を削除できます。これにより、次の近似が生成されます:
v <= 2^64 / l
2^11 バイトより大きいパケットから保護を解除しようとしないエンドポイントは、最大 2^57 パケットから保護を解除しようとすることができます。処理されたパケットのサイズを制限しないエンドポイントは、最大 2^52 パケットから保護を解除しようとすることができます。
AEAD_AES_256_GCM の場合、同じ項が支配的ですが、k の値が大きいため、次の近似が生成されます:
v <= 2^192 / l
これは AEAD_AES_128_GCM の制限よりかなり大きいです。ただし、本文書では、いずれかの制限が許容できるほど大きいため、両方の関数に同じ制限を適用することを推奨しています。
B.2. AEAD_AES_128_CCM の使用制限の解析
TLS [TLS13] および [AEBounds] は、AEAD_AES_128_CCM の使用制限を指定していません。ただし、QUIC で使用される AEAD には、機密性と完全性の両方が維持されることを保証する使用制限が必要です。本セクションではその解析を文書化します。
[CCM-ANALYSIS] がこの解析の基礎として使用されます。機密性について、定理2は、攻撃者が理想的な疑似ランダム順列 (PRP) に対して次を超えない識別優位性を得ることを確立します:
(2l * q)^2 / 2^n
定理1の完全性制限は、同じ数のメッセージに対して攻撃者に厳密に高い優位性を提供します。機密性優位性と完全性優位性の目標が同じであるため、定理1のみを考慮する必要があります。
定理1は、攻撃者が理想的な PRP に対して次を超えない優位性を得ることを確立します:
v / 2^t + (2l * (v + q))^2 / 2^n
"t" と "n" はどちらも 128 であるため、最初の項は2番目の項に比べて無視できるため、結果に大きな影響を与えずにその項を削除できます。
これにより、機密性のみの定理によって生成される制限と同じ制限で、暗号化と復号化の両方の試行を組み合わせる関係が生成されます。2^-57 の目標優位性の場合、これは次のようになります:
v + q <= 2^34.5 / l
"q = v" を設定することにより、機密性と完全性の両方の制限の値を生成できます。したがって、パケットを 2^11 バイトに制限するエンドポイントは、機密性と完全性の両方の制限が 2^26.5 パケットです。パケットサイズを制限しないエンドポイントの制限は 2^21.5 です。
貢献者 (Contributors)
IETF QUIC ワーキンググループは、多くの人々から多大な支援を受けました。以下の方々が本文書に実質的な貢献をしました:
(貢献者リストは省略)
著者の連絡先 (Authors' Addresses)
Martin Thomson (editor)
Mozilla
Email: [email protected]
Sean Turner (editor)
sn3rd
Email: [email protected]