全ブランチから検索ググったけどmacOSでぱっと動くのがなかったのでメモがてら書く。Interimで、ハンドシェイクプロトコルの再設計案の採用が決まりました。Docを見てもらえばいいとして、ざっくりいうと、TLSスタックをふたつに分割しパケットはQUICがレイアウトしたバイト列をTLSスタックが提供するAPIを使って暗号化注1して生成ハンドシェイクメッセージについては、平文のメッセージをTLSスタックとQUICスタックとの間で交換し、QUICスタック側で上記手法によるパケット化暗号化を行うというものです。これにより、たとえばサーバがハンドシェイク時に送出するパケットの構造は以下のようにかわります。赤は難読化(つまり正当なパケットと攻撃との区別がつかない)、黄は未認証の暗号化(通信は暗号化されているが、誰と話しているかはわからない)、青は認証済の暗号化を示しています。従来は5層のレイヤで2重の暗号化をしていたのが、4層のレイヤで1重の暗号化を行うようににかわることがわかります。このような変更を採用することになったのでしょうか。伝統的なTLSスタックにおいて、TLS接続はTCP/IP接続の拡張として表現されます。JavaのSSLSocketはSocketを拡張したクラスです。I/Oに変換されます。この手法の問題は、ソケットの管理が困難になりがちなことです。イベントドリブンなプログラムにおいては、同期I/Oではなく非同期I/Oが求められます。このことは、TLSスタックに非同期I/O用のモードを別途設けるか、あるいは、TLSスタックに対し、アプリケーション側からソケットのようなAPIをもつバッファを提供してやる必要がでてくることを意味します。ヘッドオブラインブロッキングの影響を制御するために、暗号化するブロックサイズを制御し、ブロック単位で送信しようにも、そのような制御を可能にするインターフェイスが存在しないという問題があります注2。1.3むけに採用してきました。▪️「トランスポート層による暗号化」の必要性TCP上でTLSを使う上での問題点のひとつが、第三者がいつでも接続をリセットできるという点です。このような攻撃が可能なのは、TCP自体が認証付き暗号によって保護されておらず、リセットを引き起こすようなパケットを誰でも生成できてしまうからです。このようなトランスポート層への攻撃に対処するため、QUICのこれまでのドラフトでは、QUICの上で動くTLSスタックから鍵を「エクスポート」し、この鍵を使ってパケットを暗号化してきました。Huitema氏は「TLSの利用形態はレイヤからコンポーネントへ変化している」と指摘してきました。プログラミング上の都合のみならず、プロトコル設計上の都合からも、従来のTLSをレイヤとして利用するアプローチが限界に来ていたことがわかります。利用形態の変化はともかく、これまでのドラフトのアプローチは以下の各点の問題を抱えるものでした。Rescorla氏によるDTLSへの移行提案がありましたが、DTLSのパケットフォーマットがQUICが必要する機能を提供できない点や、再送制御がハンドシェイク前と後と異なってしまう点などが問題視されていました。それを踏まえ、DTLSという、QUICとは異なるプロトコルを組み合わせるくらいなら、いっそTLSスタックを分割して、QUICのパケットフォーマットをそのまま使おう、というのが、今回の提案の骨子だったわけです。1.3と同じタイミングで暗号鍵を変更するため、ハンドシェイク中の攻撃耐性が向上する注3鍵管理をTLSスタックに依存できるようになるので、QUICスタックの品質向上に寄与するパケットフォーマットは引き続きQUICワーキンググループで設計管理、拡張されるといった点があげられることになります。この提案が受け入れられた背景として、TLSスタックの従来のAPIに限界があることが共通理解となっていた、という点もあげられるでしょう。▪️まとめQUICではTLSをハンドシェイクと暗号化という2つの機能に分割して使用することになりました。このことは品質向上につながります。1.3に加え、第3のパケットフォーマットをもつプロトコルが誕生することを意味します。今後策定されるプロトコルにおいて暗号化が必須であることを考えると、TLSのハンドシェイクメッセージを使いつつ、プロトコル毎に異なるパケットフォーマットを定義する流れが一般化するかもしれません。長期的にみると、TLSの解体と再構成につながるかもしれませんね。