あどけない話

Internet technologies

TLS 1.3 開発日記 その29 Key update

TLS 1.2で暗号路の鍵を更新する場合は、ハンドシェイクをやり直す(再ネゴシエーションする)必要があった。実装の視点からいうと、鍵更新はハンドシェイクに対して同期的だった訳だ。

TLS 1.3では、サーバやクライアントがハンドシェイクをし直すことなく、いつでも鍵を更新できる。(TLS 1.3 には再ネゴシエーションはない。)つまり、鍵更新はハンドシェイクに対して非同期的になった。プログラマーにとっては、腕が試されることになる。

TLS 1.3の鍵更新メッセージの書式は、以下のように定義されている。

enum {
    update_not_requested(0), update_requested(1), (255)
} KeyUpdateRequest;

struct {
    KeyUpdateRequest request_update;
} KeyUpdate;

典型的な使い方はこうだ:

  1. AがKeyUpdate(update_requested)を送り、送信側の鍵を更新
  2. BはKeyUpdate(update_requested)を受け取ったら受信側の鍵を更新し、KeyUpdate(update_not_requested)を送り、送信側の鍵を更新
  3. AがKeyUpdate(update_not_requested)を受け取ったら、受信側の鍵を更新

AとBが同時にKeyUpdate(update_requested)を送ってもよく、その場合、単に2回鍵が更新された状態に落ち着く。

さて、問題はここからだ。

私は update_not_requested を update_requested への応答だと解釈していた。そこで、update_requested を送信してない状態で、update_not_requested を受け取ると、エラーにしていた。しかし、レビュアーの Olivier さんから、一方向の更新も許されるのではないかと指摘を受けた。そう思った理由は、OpenSSL の s_client が、

  • k コマンドの場合、一方向の鍵を更新しようとし (update_not_requested を送信)
  • K コマンドの場合、双方向の鍵を更新しようとする (update_requested を送信)

からだった。

slack のTLS 1.3の実装者が集まるチャンネルに話題を振ったところ

  • 許されていない:無視すべき
  • 許されていない:エラーにすべき
  • 許されている

の3つの解釈が出てきて、やはり仕様が曖昧だと分かった。

結局、編集者の Eric さんが降臨し、「許されている」と言って決着した。

結論:TLS 1.3 では、一方向の鍵更新もOK!