要約

  • TLS 1.3 の certificate_authorities は、DER で符号化された識別名を順序付きで運ぶ。受信側の証明書チェーン選択を助けるが、CA 証明書、信頼された鍵、完成した検証パス、業務上の権限は運ばない。
  • ClientHello でクライアントからサーバーへ送る場合と、CertificateRequest でサーバーからクライアントへ送る場合がある。同じ拡張でも、情報の所有者と判断の向きは反対である。
  • 実行証跡は、リストの生成、資格情報の選択、パス検証、アプリケーション認可を別々の結果として残さなければならない。

「選べる」と「使わせる」の間

相互 TLS の現場では、端末が複数のクライアント証明書を持つことがある。CertificateRequest の CA 名に合わせてライブラリが一枚を選び、秘密鍵の所持を証明し、サーバーが現在の信頼アンカーまでパスを組み立てる。ここまでは TLS と PKI の仕事だ。

ところが、証明書の SAN が別のワークロード名前空間を指す、テナント登録が切れている、必要な役割がない、といった理由で業務要求は拒否できる。検証成功は「この資格情報を認証できた」という結果であり、「この注文、配備、ルート変更を許す」という結果ではない。

この差を mtls_ca_allowed の一項目に押し込めると、事故時に何が起きたか分からなくなる。リストを誰が作ったのか、候補はなぜ落ちたのか、どのアンカーが使われたのか、最終的にどの主体へ何を許したのかを復元できない。

識別名は鍵を指す札にすぎない

IANA の拡張値 47 が certificate_authorities である。RFC 9846 は、内容を一つ以上の DER 符号化 X.501 識別名と定義する。名称は望ましい信頼アンカーや下位 CA を示し、対向の証明書選択を導くために使われる。

しかし、識別名には公開鍵も Basic Constraints も Name Constraints も証明書ポリシーも含まれない。同じ subject を持つ別鍵の CA 証明書が存在し得る。名前が一致しても、送信側がどの鍵を信頼しているかは確定しない。

信頼アンカーは独立に配布されるため、通信上のチェーンから省かれることもある。RFC 5280 に基づく検証は、アンカー、署名、有効期間、用途、制約、ポリシー入力を実物で評価する。リスト上の名前だけでは代用できない。

したがって、presence から言えるのは「このメッセージでこの符号化名が広告された」までである。配下の全証明書を受け入れる証明にはならない。逆に omission も全面的な不信頼を意味しない。プライバシーのために縮めたリストや、選択用途だけの部分集合かもしれない。

ClientHello と CertificateRequest は別の運用面

ClientHello の CA リストは、サーバーが提示するサーバー証明書や代替チェーンの選択に影響する。CertificateRequest のリストは、クライアントが返すクライアント証明書を絞り込む。

クライアント起点のリストには情報開示が伴う。OpenSSL は、クライアント側の CA 名がサーバーへ平文で送られると説明する。企業の信頼ストアをそのまま出力すれば、内部組織名や PKI 構造を相手に渡すことになる。

サーバー起点では、資格情報の曖昧さを減らせる一方、巨大な名前集合はハンドシェイクのサイズと処理を増やす。TLS 1.3 では旧来の trusted_ca_keys は使われない。監視は交渉バージョン、方向、メッセージ、拡張値を組にして持つ必要がある。

証明書選択は一条件の検索ではない

CA 名は選択材料の一つにすぎない。signature_algorithms、必要に応じて signature_algorithms_cert、鍵種別、秘密鍵の有無、証明書署名、Key Usage、EKU、SNI、OID フィルター、ローカルで構築可能なチェーンも候補を削る。

だから、選ばれなかった候補の理由が重要になる。名前は合うが EKU が違う、鍵が見つからない、許容される署名方式がない、望ましい CA へ到達するチェーンがない、といった差は、最後の leaf 指紋だけでは見えない。

適切なクライアント証明書がなければ、TLS 1.3 は空の Certificate を送る。サーバーはプロファイルに従って継続するか、certificate_required で拒否できる。無関係な証明書へ黙ってフォールバックするより、空という結果を保持する方が安全である。

広告リストと検証ストアを意図的に食い違わせる

OpenSSL では、対向に送る CA 名リストと、証明書検証に使う信頼ストアが別の API 群である。リストを設定しても、その CA が信頼対象になるわけではない。検証場所は別途ロードする。

この分離は試験に使える。CA の subject 名を広告しながら、対応する鍵を検証ストアから外す。クライアントは名称に合うチェーンを選べるが、サーバーは unknown_ca で拒否し得る。逆向きに、信頼済みチェーンがリストに出ていない状態も作れる。

これは矛盾ではなく、リスト生成と信頼判定が異なる稼働状態である証拠だ。ホットリロードで一方だけが変わる可能性もある。それぞれの世代、ハッシュ、起動時刻を記録し、接続が実際に参照した組み合わせを結び付ける必要がある。

さらに OpenSSL のクライアント CA 名読み込みは subject を抽出し、入力を CA 証明書だけに限定しない。ファイル読み込み成功は、各項目が信頼できる CA であることの証明ではない。

パス検証の後にアプリケーション主体が生まれる

受け取ったチェーンについて、検証器はアンカー、署名、有効性、制約、用途を評価する。プロトコル固有の識別規則は SAN などを解釈する。それでも、テナントや役割への割り当てはアプリケーションの別判断である。

主体の対応付けは、SAN の形式、issuer と subject の組、ポリシー OID、登録記録、外部 entitlement に依存し得る。正しい証明書を拒否することは、権限管理として正しい場合がある。

またクライアントは、ハンドシェイクが終わっただけでサーバーが相互認証主体として認めたと断定できない。アプリケーション層で明示結果を返す設計が必要になる。TLS 完了を役割付与へ短絡させてはならない。

コールバックの存在ではなく実行を測る

OpenSSL、GnuTLS、BoringSSL は選択や検証のコールバックを提供する。登録済みという構成情報は能力を示すだけだ。接続 ID と時刻を持つ呼び出し記録によって初めて、そのハンドシェイクで判断が走ったと証明できる。

BoringSSL の一部の CA 値は、証明書選択コールバックまたは停止中ハンドシェイクの寿命内だけ有効である。恒久証跡には、有効範囲内で DER 値をコピーまたはハッシュする。GnuTLS でも資格情報選択と信頼リスト検証は別機能である。

PSK による TLS 1.3 セッション再開では、主ハンドシェイクで新たな CertificateRequest を行わない経路がある。コールバックが走っていないのに「CA リスト確認済み」「クライアント証明書を再検証」と計上してはいけない。

権限を混ぜないための反証試験

広告した識別名に対応する鍵を信頼しない。subject が同じで鍵が違う二つの CA の片方だけを信頼する。名称は合うが期限、EKU、ポリシー、秘密鍵の条件を満たさない証明書を候補に入れ、除外理由を保存する。

パスを成功させた後、テナント境界で主体を拒否する。適切な資格情報をなくし、空 Certificate とサーバーの明示判断を観測する。リストだけ、次に信頼ストアだけを更新し、世代差の警報を確認する。

ClientHello の名前集合を採取して開示量を評価する。大量・長大な名前でサイズ限界を試す。再開接続で新規認証メトリクスが増えないことを確かめる。installed、invoked、selected、verified、authorized の各状態を別々に数える。

必要な証拠の階段は、広告名、候補、選択資格情報、秘密鍵所持、検証パス、解釈された主体、許可された操作である。下段の成功が上段の権限を先取りしてはならない。

出典