あどけない話

インターネットに関する技術的な話など

TLS 1.3 開発日記 その9 NewSessionTicket

kazuho さんと議論したメモ:

サーバが送るNewSessionTicketは、当然セッションチケットを入れないければならない。以下の構造では ticket がそれにあたる:

struct {
  uint32 ticket_lifetime;
  uint32 ticket_age_add;
  opaque ticket<1..2^16-1>;
  Extension extensions<0..2^16-2>;
} NewSessionTicket;

この ticket は、キースケジュールの最後に出てきた resumption_secret をサーバ自身だけが復号化できるように暗号化したものである。resumption_secret を算出するには、Client Finished が必要である。

というわけで、普通に考えるとNewSessionTicketを送れるのは、Client Finishedを受け取った後になる。しかし、Client Finishedは予測できるので、Server Finished を送った直後に、予測を元に生成した NewSessionTicket を送ることもできる。

サーバは、どちらのタイミングで NewSessionTicket を送るべきだろうか?

TLS 1.3 の API として、以下の3つが用意されているとしよう:

  • handshake()
  • sendAppData()
  • recvAppData()

サーバが handshake() を呼ぶ場合、Client Finished の到着を待つのではなく、Server Finished を送った直後に戻って来てほしい。なぜなら、メール系のプロトコルでは、サーバから先に greeting を送るからだ。greeting は 0.5 RTT で送りたい。

Web系のサーバでは、クライアントから先にデータがやってくるので、handshake() の後にすぐに recvAppData() を呼ぶだろう。recvAppData() は、Client Finished を受信して検証した後、アプリケーションのデータを受信して戻る。

recvAppData()は、データを受信することだけが期待されており、何かを送信するとユーザが驚くと思われる。だから、recvAppData() は NewSessionTicket を送ってはいけない。

そいうわけで、送受信できる handshake() が予測を元にNewSessionTicketをあらかじめ送るのが筋がよさそうに思える。