要約
- TLS 1.3の
HelloRetryRequestは交渉の再出発ではない。二度目のClientHelloで変えられるのは、指定された鍵共有、early dataの削除、cookieの返送、binderの再計算など、仕様が明示した項目に限られる。 ClientHello1は、そのダイジェストを持つ合成message_hashへ置き換えられ、再試行と後続メッセージとともに認証される。ステートレス処理は履歴を圧縮するが、履歴を消去しない。- 運用証拠には二つのClientHello、要求理由、許容差分、cookie方針、最終グループ、アラート、追加遅延が必要だ。接続成功だけでは再試行の正当性も、最終グループがクライアント本来の選択だったことも証明できない。
途中から始まる記録が作った誤認
観測画面では、二度目のClientHelloが一つの鍵共有を送り、ServerHelloが同じグループを選び、その後のCertificateVerifyとFinishedも成功していた。システムは自然に「クライアントがこのグループを提示し、サーバーが採用した」と要約した。
欠けていた最初のメッセージでは、クライアントは複数の supported_groupsを列挙しつつ、別のグループだけをkey_shareとして予測送信していた。サーバーはその予測を採らず、既に対応可能と宣言されながら共有値が届いていないグループをHelloRetryRequestで指定した。二度目の単一共有はクライアントの初期選好ではなく、サーバー要求への回答である。
設定上の許可、ワイヤ上の対応宣言、最初に予測した共有、再試行で求められた共有、最終選択は別々の事実だ。最初のフライトを捨てる監視は、サーバー判断をクライアント選好へ逆輸入し、余分な往復をネットワーク遅延へ誤配賦する。
許可リストとしての再試行
現行TLS 1.3仕様では、二度目のClientHelloは原則として最初と同じでなければならない。HRRにkey_shareがあれば、指定グループの新しい共有一つへ置き換える。最初に0-RTTを試みたならearly_dataを外す。cookieが与えられたならその内容をコピーする。PSK binderは再試行履歴を含めて計算し直す。将来の拡張による変更も、HRR内にその拡張が存在し、変更規則を定義している場合だけ許される。
これは「だいたい同じ」にする規定ではない。変更権限をフィールド単位で限定する許可リストである。
指定グループは最初のsupported_groupsに含まれていなければならず、最初のkey_shareに既に存在していてもならない。変化を生まないHRR、二度目のHRR、提示されていない暗号スイート、要求と異なるServerHelloグループは拒否対象となる。
つまりサーバーが持つのは、一度だけ有効な修正を求める権限であって、全フィールドを再交渉したり、クライアントが別方針を受け入れるまで要求を繰り返したりする権限ではない。
message_hashは最初の提案を残す
TLSの鍵導出や認証は、順序づけられたハンドシェイク記録のハッシュに依存する。ステートレスなサーバーがcookieを発行して一時状態を捨てる場合、各クライアントの完全なClientHelloや実装固有の中間状態を保持するのは重い。
そこでClientHello1の代わりに、タイプ254の合成message_hashを置き、その本文にHash(ClientHello1)を入れる。その後にHelloRetryRequest、ClientHello2、ServerHello、認証メッセージが連なる。CertificateVerify、Finished、再試行後のPSK binderは、最初の提案を無かったことにできない。
ただしハッシュは元のバイト列を復元する記録ではない。端点は連続性を暗号学的に検証できても、運用担当者は最初にどの拡張や共有があったかをハッシュだけから説明できない。プロトコルのコミットメントと、事故説明のためのキャプチャは補完関係にある。
対応、予測、選択を分離する
TLS 1.3クライアントは往復を減らすため、最初のメッセージに鍵共有を予測して入れる。対応する全グループの共有を生成すればClientHelloは大きくなり計算も増える。一つだけなら軽いが、サーバーが別の対応グループを望む場合にHRRが必要になる。
ハイブリッド耐量子グループではこの選択がより大きい。OpenSSLはグループの組と予測共有を明示的に設定できる。大きな最初のClientHelloはTCPセグメント境界を越え、壊れたファイアウォールに遭遇し得る一方、共有を後送りすれば、そのグループを明示的に求めるサーバーだけが追加往復を負担する。GnuTLSもグループ優先度と単一共有送信を別の制御としている。
したがって「Xに対応」という資産台帳だけでは足りない。実装がXを知る、設定がXを許可する、最初の一覧にXがある、共有を先送りする、サーバーがXを要求する、最終的にXを使う、という状態はそれぞれ記録されるべきだ。
early dataは迂回路を通れない
最初のClientHelloにearly_dataがあっても、二度目では削除される。HRRはそのハンドシェイクで0-RTTが受理されなかった証拠である。
クライアントはHRRを受け取る前にアプリケーションデータを送っているかもしれない。操作を再送してよいか、応答を既に観測したか、副作用をどう照合するかはアプリケーションの責任だ。最終的に1-RTT接続が成功しても、操作が自動的に冪等になるわけではない。
テレメトリは、early dataの試行、HRRによる不受理、アプリケーションの再送判断、最終結果を分ける必要がある。「再開成功」の一項目では重要な状態変化が消える。
cookieが示せる範囲
サーバーはHRRに不透明なcookieを入れ、二度目のHelloで同じ内容を返させられる。最初のHelloのハッシュ、選択パラメータ、時刻、経路文脈などを持たせ、完全性保護によって改変を検出できる。ただし証明力は鍵管理、有効期間、検証規則に限定される。
DTLS 1.3では、cookieを見かけ上のクライアントアドレスへ結び付け、大きな応答の前に戻り経路を確かめる用途がある。仕様が鍵ローテーション、重複受理期間、タイムスタンプを扱うのは、ステートレスなトークンにも寿命があるためだ。
到達可能性は身元ではない。cookieの返送は、その時間帯に誰かがそのアドレスで通信を受け取れたことを示し得るが、人、端末の役割、アプリケーション権限を示さない。正しいcookieも、二つのClientHelloの差分検査を不要にはしない。
拡張も同じ履歴へ参加する
Encrypted Client Helloは境界を示すよい例だ。HRRのrandomは固定値なので、ECHは通常のServerHelloと同じ場所へ受理確認を書けない。そこでencrypted_client_hello拡張を使い、内部ClientHelloと修正済みHRRの記録に確認値を結び付ける。
これはECH全体を論じるためではない。新しい機能も、変更可能な項目、信号の場所、既存履歴への認証方法を定義しなければならないという証拠である。拡張が再試行権限を無制限にすることはない。
事故後にも使える証拠
強い記録はClientHello1のハッシュと許可された解析項目、完全なHRR、cookieの秘匿化済みハッシュ、ClientHello2の解析項目、最終ServerHelloを保存する。さらに、それぞれの判断を生成した実装版と設定版を結び付ける。
グループについては、有効一覧、広告順、予測共有、サーバー優先モード、要求、返送、最終選択を分ける。再試行については、理由、差分の適合、拒否アラート、二度目の要求を記録する。影響については、追加RTT、二つのHelloのバイト数、分割、early-data結果、完了率、クライアント群を測る。
負の証拠も必要だ。未広告グループ、既に共有済みのグループ、変化のない要求、暗号スイートの変更、二度目のHRR、不一致なServerHelloを拒否できるかを試験する。BoringSSLのテストランナーが異常系を多く持つのは、拒否も相互運用性の一部だからである。
完了した接続は結末であり、それ以前の判断すべての正しさを証明するものではない。正当性は、制約された変更の連鎖から生まれる。
情報源
- https://www.rfc-editor.org/rfc/rfc9846.html
- https://www.rfc-editor.org/rfc/rfc9147.html
- https://www.rfc-editor.org/rfc/rfc9849.html
- https://www.rfc-editor.org/rfc/rfc7919.html
- https://www.rfc-editor.org/rfc/rfc8422.html
- https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
- https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml
- https://docs.openssl.org/4.0/man3/SSL_CTX_set1_curves/
- https://docs.openssl.org/4.0/man1/openssl-s_client/
- https://gnutls.org/manual/html_node/Priority-Strings.html
- https://www.gnutls.org/manual/gnutls.html
- https://boringssl.googlesource.com/boringssl/+/refs/heads/main/ssl/test/runner/handshake_server.go
- https://blog.cloudflare.com/rfc-8446-aka-tls-1-3/
- https://heng.lu/running-code-primary-the-patch-needed-to-preserve-the-internet-original-design/
会員向け解説
プロフィールの詳細
適切な会員レベルでログインすると、解説全文と出典メモをご覧いただけます。
Strategic Circle 限定
Strategic Circle
すべての読者に公開されています。参加してログインすると プロフィール解説 を閲覧できます。
Strategic Circle に参加Leadership Alliance 会員限定
Leadership Alliance
対象となる IP 資産の所有者・管理者向けです。ログインすると Leadership Alliance の解説を閲覧できます。
Leadership Alliance に参加
