TLS 1.3 ID21までの仕様は、
- ServerHelloの書式がTLS 1.2と異なる
- ChangeCipherSpecがない
という特徴があった。
ServerHelloが異なるということは、TLS 1.3に非対応であったWiresharkで表示できなくて辛いとか、パーサーの中で分岐しなければならないので関数プログラミングの考えでコードが書きにくいなどの問題があった。
その後、はやり世の中にはTLS 1.3を遮断するミドルボックスが少数ながらも存在することが分かり、これらのミドルボックスを騙すための方法が考案された。現在 PR1091 で議論中だが、開発者の間ではこのPRをマージした版がID22とすることで合意が取れている。その方法とはこうだ:
- ServerHelloの書式をTLS 1.2と同じにする
- バージョンはTLS 1.2を指定する
- 圧縮方式が復活。常に0
- セッションIDが復活。互換性モードの場合、クライアントが指定したセッションIDをコピーする
- サーバーが選択したバージョンは、supported_versions拡張でクライアントへ伝える
- HelloRetryRequestを廃止する
- ServerHelloを利用し、Randomに特定の値を持つServerHelloをHelloRetryRequestとみなす
- レコードのバージョンは、TLS 1.2とする
- ChangeCipherSpecを復活させる
- ChangeCipherSpecを受け取ったら単に無視する
- 互換モードの場合、適切なタイミングでChangeCipherSpecを送ってよい
確かに、これならミドルボックスを騙せそうだ。というか、初めからこうしておけばよかったのに。
例によって、IETFのHackathon前に、OpenSSLとHaskell tlsがこの仕様をサポートし、ある程度の相互互換性を確かめた後、11月11日と12日に開催されたIETF 100で他の実装が追いついて来るという流れになった。僕は日本から遠隔参加するために、サーバーを立ち上げたり、クライアントのバイナリを作成したりした。
IETF 1.3のHackathonでは、遠隔参加が活発だった TLS 1.3チームが "best remote participant" 賞を頂いたそうだ。景品は、IETFに参加しているTLS 1.3チームのメンバーが受け取ったとこのこと。遠隔参加賞なのにぃ!