要約
- RFC 9846 の KeyUpdate は、送信側の application traffic secret を一方向だけ次世代へ進める。更新message自身は旧送信鍵で保護され、その後のrecordから新世代が使われる。
update_requestedは相手に逆方向の更新を求めるが、無制限の作業権限ではない。方向は独立し、crossしたrequestは二世代進むことがあり、silent中の複数requestは一回にまとめられ、epochとAEADの上限はlocalに執行される。- 証拠は API scheduling、wireへの送出、peerの受理、new-generation data成功を分離する。これらがそろっても、旧secretのmemory消去、再認証、application authorizationまでは証明しない。
一行の成功logを四つに分解する
長時間接続の試験で、server側から update_requested を発行する。applicationが最初に観測するのはAPIの成功かもしれない。しかしOpenSSLでは実際の処理が次のI/Oまで遅れることがある。まだwireには何も出ていない可能性がある。
TLS stackが送るKeyUpdate recordは旧server送信鍵で暗号化される。続くserver発recordは新しいserver application traffic secretを使う。clientは旧受信鍵でtransitionを認証した後に、対応するreceive chainを進める。逆方向を更新する返信はclient自身の旧送信鍵で送り、その後のclient recordが新世代になる。
この順序から、接続全体に一つのepochしかないという見方は成立しない。sendとreceive、clientとserverの状態は対応していても、観測時刻は同じではない。incident時に必要なのは「双方とも7」ではなく、どの方向が、どのmessageを根拠に、いつ6から7へ移ったかである。
現行仕様は RFC 9846
2026年のRFC 9846はRFC 8446をobsoletesし、wire上のTLS 1.3との互換性を維持した。KeyUpdateはhandshake type 24であり、値は update_not_requested(0) と update_requested(1) だけである。Finished前の受信は unexpected_message、未定義値は illegal_parameter となる。
更新messageはkey change直前のrecord boundaryに整列しなければならない。新世代のrecordを受理する前に、旧鍵で保護されたKeyUpdateを受理する必要がある。このbridgeを省けば、truncation attackの余地が生じる。したがって「次鍵でdecryptできた」は、transition authorizationの代わりにならない。
次のsecretは現在の方向別secretから traffic upd labelでHKDF展開される。新しいkeyとIVを得た後、旧secretとkeyは削除すべきとされる。現行仕様は送信epochを 2^48-1 以下に制限し、受信側が相手の上限を強制することは禁じる。応答更新が自分の上限を越えるなら実行せず、request flagを無視すべきである。
Reciprocal request の力は有限である
update_requested は単なるhintではない。受信側は原則として、次のApplication Dataを送る前に update_not_requested のKeyUpdateを返す。それでもpeerがconnection schedulerを所有するわけではない。
未解決のrequested updateがある間、同じ送信側は次のrequested updateを送れない。受信側がsilentな間に複数届いても、応答は一回に集約できる。両側が同時にrequestしてmessageがcrossすると、それぞれが追加応答を送り、両方向が二世代進む場合がある。
仕様は中心的なrekey masterを置かず、並行する二つの主体を扱う。認証されたpeerはbounded requestを出せるが、CPU budget、I/O scheduling、connection termination、memory deletionの決定までは取得しない。
旧secretの削除は遠隔証明できない
new-generation recordが成功すれば、双方がその方向で互換なsecretを導出したことは分かる。分からないことの方が重要である。remote heap、HSM slot、kernel offload、core dump、backupに旧materialが残っているかはwireから見えない。
Forward secrecy after updateは、旧世代を本当に削除するlocal code pathに依存する。peerの返信をもって「安全消去済み」と記録するのは、protocol interoperabilityをcompliance attestationにすり替える行為になる。
KeyUpdateはidentityも更新しない。certificate verification、client identity、service name、application permissionは既存connectionの判断を引き継ぐ。新しいrecord keyは暗号上のfreshnessを与えるが、compromised endpointや誤ったbusiness authorizationを修復しない。
実装の違いが完了時刻を変える
OpenSSLの SSL_key_update() はhandshake完了後に使い、実処理はread/writeまたは明示的なhandshake driveで進む。applicationはpending writeとの順序を管理する必要がある。
GnuTLSの gnutls_session_key_update() はlocal送信方向だけを更新でき、GNUTLS_KU_PEER で相手にも更新を依頼する。record sendと同様にnonblocking結果を返し得る。manualはrekeyとre-authenticationを別機能として説明する。
rustlsの refresh_traffic_keys() も更新messageをscheduleする。通常はcipher suiteのconfidentiality limitをlibraryが追跡するが、kernel APIでrecord protectionを外部化した場合、count、refresh、abortは利用側の責任となる。API名が同じでも、authority boundaryはintegrationによって変わる。
QUICとDTLSを同じeventにしない
QUICはTLS 1.3をhandshakeに使うが、TLS KeyUpdateを送ることを禁止する。QUIC v1はKey Phase、ACK、quic ku 派生を用いる。TLS type 24だけを数えるmonitorは、正常なQUIC更新をゼロと誤認する。
DTLS 1.3はKeyUpdateを使いながら、lossとreorderingのためepochとACKを追加し、遅延datagram用に旧受信materialを保持する。返信がrequestとcrossし得るため、返信自体はacknowledgementではない。上限に近い場合の応答規則もstream TLSと同一ではない。
従ってevent schemaにはtransportとversionが必須である。曖昧な rekeyed=true では、三つの異なる証拠体系を復元できない。
Secretを書かない証拠設計
必要なのはsecret値ではなく、connection reference、role、transport、direction、old/new generation、initiator、request flag、旧鍵transitionの認証、record alignment、pending write、最初のnew-generation record、cross/coalesce、rate-limit判断、terminal alertである。
状態はscheduled、emitted、accepted、data-succeededに分ける。TLS 1.3のKeyUpdateは暗号化されるため、packet capture単独ではmessageを同定しにくい。isolated testではendpoint callback、counter、限定key logを対応させられるが、production observabilityへsecretを常時流してはならない。
memory erasureは別のlocal assurance recordに残す。関連付けはしても、wire eventで代用しない。
Sources
- RFC 9846 — 現行 TLS 1.3
- RFC 8446 — 旧 TLS 1.3 specification
- RFC 9001 — Using TLS to Secure QUIC
- RFC 9147 — DTLS 1.3
- IANA — TLS Parameters
- OpenSSL — SSL_key_update
- GnuTLS — Core API reference
- GnuTLS — TLS 1.3 re-authentication and re-key
- rustls — ConnectionCommon
- rustls — kernel connection API
- Heng Lu — Running-Code Primacy
- Heng Lu — Minimum Initial Specification
会員向け解説
プロフィールの詳細
適切な会員レベルでログインすると、解説全文と出典メモをご覧いただけます。
Strategic Circle 限定
Strategic Circle
すべての読者に公開されています。参加してログインすると プロフィール解説 を閲覧できます。
Strategic Circle に参加Leadership Alliance 会員限定
Leadership Alliance
対象となる IP 資産の所有者・管理者向けです。ログインすると Leadership Alliance の解説を閲覧できます。
Leadership Alliance に参加
