RFC 9846 TLS 2026年7月
Rescorla 標準化過程 [ページ]
ストリーム:
インターネット技術タスクフォース(IETF)
RFC:
9846
廃止対象:
5077, 5246, 6961, 7627, 8422, 8446
更新対象:
5705, 6066
カテゴリ:
標準化過程
公開日:
ISSN:
2070-1721
著者:
E. Rescorla
独立

RFC 9846

トランスポート層セキュリティ(TLS)プロトコル バージョン1.3

概要

本文書は、Transport Layer Security (TLS)プロトコルのバージョン1.3を規定する。TLSにより、クライアント/サーバーアプリケーションは、 盗聴、改ざん、およびメッセージ偽造を防止するよう設計された方法で インターネットを介して通信できる。

本文書は、TLS 1.3を規定していたRFC 8446を 廃止する。本文書は、RFC 5246(TLS 1.2を規定)およびRFC 5077、 6961、7627、8422(いずれもTLS 1.2以前に関連する)を廃止し、 RFC 5705および6066を更新する。また、本文書はTLS 1.2の実装に対する新たな要件も 規定する。

本文書の位置付け

これはインターネット標準化過程文書である。

本文書は、インターネット技術タスクフォース (IETF)による成果物である。本文書はIETFコミュニティの合意を示すものである。本文書は 公開レビューを受け、インターネット技術運営グループ (IESG)によって公開が承認されている。インターネット標準に関する詳細な 情報は、RFC 7841の第2節で 入手できる。

本文書の現在の状態、正誤情報、および 本文書に関するフィードバックの提供方法については、 https://www.rfc-editor.org/info/rfc9846で確認できる。

目次

1. 序論

TLSの主な目的は、通信する2つのピア間にセキュアなチャネルを提供することである。 基盤となるトランスポートに対する唯一の要件は、 信頼性があり、順序どおりのデータストリームである。具体的には、 セキュアチャネルは次の特性を提供すべきである。

これらの特性は、[RFC3552]で説明されているように、 攻撃者がネットワークを完全に制御している場合でも成立すべきである。 関連するセキュリティ 特性のより完全な説明については、付録Fを参照されたい。

TLSは、次の2つの主要な構成要素からなる。

TLSはアプリケーションプロトコルに依存せず、上位レベルのプロトコルは TLSの上に透過的に階層化できる。ただし、TLS標準は、 プロトコルがTLSによってどのようにセキュリティを追加するか、 TLSハンドシェイクをどのように開始するか、および交換された認証 証明書をどのように解釈するかを規定していない。これらは、TLS上で動作する プロトコルの設計者および 実装者の判断に委ねられる。TLSを使用するアプリケーション プロトコルは、ハンドシェイクがいつどのように 行われるか、および識別情報の検証をどのように行うかを含め、TLSがその アプリケーションプロトコルとどのように連携するかを規定しなければならない[RFC9525]は、 TLSをアプリケーション プロトコルに統合するための有用な指針を提供している。

本文書はTLSバージョン1.3を定義する。TLS 1.3は以前のバージョンと直接 互換性はないが、TLSのすべてのバージョンには、 両方のピアがサポートする共通バージョンをクライアントとサーバーが相互運用可能な形で ネゴシエートできるバージョン管理機構が組み込まれている。

本文書は、バージョン1.2 [RFC5246]、 extended master secret 拡張 [RFC7627]、およびTLS 1.2の楕円曲線 定義 [RFC8422]を含む、以前のバージョンのTLSに 取って代わり、これらを廃止する。 また、[RFC5077]で定義されたTLSチケット機構を廃止し、これを 第2.2節で定義される機構に置き換える。TLS 1.3では 鍵の導出方法が変更されているため、第7.5節で説明するように、 [RFC5705]を更新する。 エクスポーターは、コンテキストがない場合と空のコンテキストがある場合とを区別しなくなった。また、 Online Certificate Status Protocol(OCSP)メッセージの伝送方法も変更するため、[RFC6066]を更新し、 第4.5.1.1節で説明するように [RFC6961]を廃止する。

1.1. 表記規則および 用語

本文書におけるキーワード「MUST」、「MUST NOT」、「REQUIRED」、「SHALL」、 「SHALL NOT」、「SHOULD」、「SHOULD NOT」、「RECOMMENDED」、「NOT RECOMMENDED」、 「MAY」、および「OPTIONAL」は、 ここに示すようにすべて大文字で 表記されている場合に限り、BCP 14 [RFC2119] [RFC8174]に記載されているとおりに 解釈されるものとする。

次の用語を使用する。

クライアント:

TLS接続を開始するエンドポイント。

接続:

2つのエンドポイント間のトランスポート層接続。

エンドポイント:

接続のクライアントまたはサーバーのいずれか。

ハンドシェイク:

TLS内での後続の相互作用に使用する パラメーターを確立する、クライアントとサーバー間の最初のネゴシエーション。

ピア:

エンドポイント。特定のエンドポイントについて説明する場合、「ピア」は、 説明の主な対象ではない方のエンドポイントを指す。

受信者:

レコードを受信しているエンドポイント。

送信者:

レコードを送信しているエンドポイント。

サーバー:

TLS接続を開始しなかったエンドポイント。

1.2. RFC 8446との関係

TLS 1.3は当初、[RFC8446]で規定された。本文書は、 同じバージョン番号を維持し、後方互換性を備えた TLS 1.3の小規模な更新である。いくつかの要件を厳格化し、 不明確であることが判明した部分の文言を更新するとともに、 その他の編集上の改善を含む。さらに、秘密に対して用いられる 「master」という用語を削除し、「main」または用語が不要な場合には より短い名前に置き換える。本文書では、次の 具体的な技術的変更を行う。

  • 接続間でのKeyShare値の再利用を禁止する。

  • [RFC8996]によって TLS 1.0および1.1が非推奨となったため、これらのネゴシエーションを禁止する。

  • PreSharedKeysおよび HelloRetryRequestで使用するハッシュに関する曖昧さを除去する。

  • 再開をサポートしていないクライアントに、 NewSessionTicketを無視するよう要求する。

  • 鍵使用 制限を超える前に鍵の更新を開始する要件をMUSTに 引き上げ、鍵使用制限の適用範囲を明確化する。

  • 許可されるKeyUpdateメッセージの数を制限する。

  • 「close_notify」のレベルを「warning」と定義する文言を復元する。

  • 「user_canceled」に関する動作を明確化し、 「close_notify」を送信しなければならず、「user_canceled」は 無視すべきであることを要求する。

  • 汎用の「general_error」アラートを追加する。

  • CertificateRequest.extensionsの下限を 0バイトに修正する。拡張を送信しないことが可能であり、 その場合の長さは0になるため、これは 構文上の誤りであった。

  • ClientHello.extensionsの下限を修正する。これは 計算上の誤りであった。

  • NewSessionTicket.extensionsの上限を修正する。 これは計算上の誤りであった。

  • KEMベースの鍵交換の使用を反映するため、 以前は専ら(EC)DHEであった非対称鍵交換について、 より一般的な表現を使用する。

  • トランスクリプトハッシュと 将来の仕様との相互作用を明確化する。

  • [RFC9963]に合わせ、RSA PSSを要求する文言を削除する。

さらに、特にプライバシーに関して、 セキュリティに関する考慮事項にもいくつかの改善が加えられている。

1.3. TLS 1.2との 主な相違点

次に、TLS 1.2とTLS 1.3の主な機能上の相違点を示す。 これは網羅的な一覧を意図したものではなく、 多数の小さな相違点も存在する。

  • サポートされる対称暗号化アルゴリズムの一覧から、 レガシーと見なされるすべてのアルゴリズムが 削除された。残っているものはすべて、関連データ付き認証暗号 (AEAD)アルゴリズムである。暗号スイートの概念は、 認証および鍵交換機構を、 レコード保護アルゴリズム(秘密鍵の長さを含む)ならびに鍵導出関数と ハンドシェイクメッセージ認証コード(MAC)の両方で使用する ハッシュから分離するよう変更された。

  • ゼロラウンドトリップ時間(0-RTT)モードが追加され、 特定のセキュリティ特性を犠牲にする代わりに、一部のアプリケーションデータについて 接続確立時の1回のラウンドトリップを省略できるようになった。

  • 静的RSAおよびDiffie-Hellman暗号スイートは削除され、 すべての公開鍵ベースの鍵交換機構が前方秘匿性を提供するようになった。

  • ServerHello以降のすべてのハンドシェイクメッセージが暗号化されるようになった。 新たに導入されたEncryptedExtensionsメッセージにより、 以前はServerHello内で平文で送信されていたさまざまな拡張も、 機密性保護を受けられるようになった。

  • 鍵導出関数が再設計された。新しい設計では、 鍵分離特性が改善されているため、 暗号学者による分析が容易になる。基礎プリミティブとして、 HMACベースのExtract-and-Expand鍵導出関数(HKDF)が 使用される。

  • ハンドシェイク状態機械は、一貫性を高め、 ChangeCipherSpecなどの不要なメッセージ (ミドルボックス互換性のために必要な場合を除く)を削除するよう、 大幅に再構成された。

  • 楕円曲線アルゴリズムが基本仕様に含まれるようになり、 EdDSAなどの新しい署名 アルゴリズムも追加された。TLS 1.3では、各曲線について単一の点形式を使用するようにし、 点形式のネゴシエーションを削除した。

  • RSAパディングをRSA確率的署名方式(RSASSA-PSS)を使用するよう変更し、 圧縮、デジタル署名アルゴリズム(DSA)、および カスタム一時Diffie-Hellman(DHE)グループを削除するなど、 その他の暗号学的改善も行われた。

  • TLS 1.2のバージョンネゴシエーション機構は非推奨となり、 拡張内のバージョン一覧が使用されるようになった。これにより、 バージョンネゴシエーションを誤って実装している既存のサーバーとの 互換性が向上する。

  • サーバー側状態を使用する場合と使用しない場合のセッション再開、および 以前のTLSバージョンにおけるPSKベースの暗号スイートは、 単一の新しいPSK交換に置き換えられた。

  • 必要に応じて、RFCへの参照が更新版を指すように 更新された(例えば、RFC 3280ではなくRFC 5280)。

1.4. TLS 1.2に影響する更新

本文書は、TLS 1.3も サポートする実装に限らず、TLS 1.2の実装に任意で影響する いくつかの変更を定義する。

  • バージョンダウングレード保護機構について、第4.2.3節で説明する。

  • RSASSA-PSS署名方式を第4.3.3節で定義する。

  • 「supported_versions」ClientHello拡張を使用して、 ClientHelloのlegacy_versionフィールドより優先して、 使用するTLSのバージョンをネゴシエートできる。

  • 「signature_algorithms_cert」拡張により、クライアントは、 X.509証明書内で検証できる署名アルゴリズムを 示すことができる。

  • 秘密に対して用いられる「master」という用語が削除され、 「extended_master_secret」拡張 [RFC7627]は 「extended_main_secret」に改名された。

さらに、本文書は以前のバージョンのTLSに関するいくつかの適合要件を明確化する。 第 9.3節を参照されたい。

2. プロトコルの概要

セキュアチャネルで使用される暗号パラメーターは、 TLSハンドシェイクプロトコルによって生成される。TLSのこのサブプロトコルは、 クライアントとサーバーが最初に通信するときに使用される。 ハンドシェイクプロトコルにより、ピアはプロトコルバージョンをネゴシエートし、 暗号アルゴリズムを選択し、相互に認証し (クライアント認証は任意)、共有秘密鍵素材を確立できる。 ハンドシェイクが完了すると、ピアは確立された鍵を使用して、 アプリケーション層のトラフィックを保護する。

ハンドシェイクの失敗またはその他のプロトコルエラーが発生すると、 接続は終了する。その前に、任意でアラートメッセージ (第6節)が送信される場合がある。

TLSは、次の3つの基本的な鍵交換モードをサポートする。

本文書における非対称鍵交換には、有限体または楕円曲線上の Diffie-Hellmanが含まれる。 その他の拡張では、鍵カプセル化機構(KEM)の使用を定義する。

以下の図1は、基本的な完全 TLSハンドシェイクを示している。

       クライアント                                     サーバー

鍵   ^ ClientHello
交換 | + key_share*
     | + signature_algorithms*
     | + psk_key_exchange_modes*
     v + pre_shared_key*       -------->
                                                  ServerHello  ^ 鍵
                                                 + key_share*  | 交換
                                            + pre_shared_key*  v
                                        {EncryptedExtensions}  ^ サーバー
                                        {CertificateRequest*}  v パラメーター
                                               {Certificate*}  ^
                                         {CertificateVerify*}  | 認証
                                                   {Finished}  v
                               <--------  [Application Data*]
     ^ {Certificate*}
認証 | {CertificateVerify*}
     v {Finished}              -------->
       [Application Data]      <------->   [Application Data]

              +  直前に示したメッセージで送信される、
                 注目すべき拡張を示す。

              *  常に送信されるとは限らない、任意または
                 状況依存のメッセージ/拡張を示す。

              {} [sender]_handshake_traffic_secretから
                 導出された鍵を使用して保護されるメッセージを示す。

              [] [sender]_application_traffic_secret_Nから
                 導出された鍵を使用して保護されるメッセージを示す。
図1: 完全なTLS ハンドシェイクのメッセージフロー

ハンドシェイクは、上の図に示す 3つの段階からなると考えることができる。

鍵交換段階では、クライアントはClientHello (第4.2.2節)メッセージを送信する。このメッセージには、ランダムな ノンス (ClientHello.random)、提示するプロトコルバージョン、対称 暗号/ハッシュのペアの一覧、非対称鍵交換共有値の一覧 (「key_share」(第4.3.8節)拡張内)、 事前共有鍵ラベルの一覧 (「pre_shared_key」(第4.3.11節) 拡張内)、またはその両方、および 追加の拡張が含まれる可能性がある。ミドルボックス互換性のため、 追加のフィールドやメッセージが存在する場合もある。

サーバーはClientHelloを処理し、接続に適した 暗号パラメーターを決定する。その後、ネゴシエートされた接続 パラメーターを示す独自のServerHello(第4.2.3節)で 応答する。ClientHelloとServerHelloの組み合わせによって、 共有鍵が決定される。非対称 鍵確立を使用する場合、ServerHelloにはサーバーの一時的な 非対称鍵交換共有値を含む「key_share」拡張が含まれる。 サーバーの共有値は、クライアントの共有値のいずれかと同じグループに 属していなければならない。PSK鍵確立を使用する場合、 ServerHelloにはクライアントが提示したPSKのうち 選択されたものを示す「pre_shared_key」拡張が含まれる。 実装は非対称鍵交換とPSKを併用でき、その場合には 両方の拡張が提供されることに注意されたい。

次にサーバーは、サーバーパラメーターを確立するために2つのメッセージを送信する。

EncryptedExtensions:

個々の証明書に固有のものを除き、 暗号パラメーターの決定には不要なClientHello拡張への応答。 [第4.4.1節

CertificateRequest:

証明書ベースのクライアント認証を行う場合に、 その証明書に求めるパラメーター。クライアント認証を行わない場合、 このメッセージは省略される。[第4.4.2節

最後に、クライアントとサーバーは認証メッセージを交換する。TLSは、 証明書ベースの認証が必要になるたびに、 同じメッセージ群を使用する。(PSKベースの認証は、 鍵交換の副作用として行われる。) 具体的には、次のとおりである。

Certificate:

エンドポイントの証明書および証明書ごとの拡張。 サーバーが証明書による認証を行わない場合はサーバーによって省略され、 サーバーがCertificateRequestを送信しなかった場合 (したがって、クライアントが証明書による認証を行うべきでないことを示す) はクライアントによって省略される。生の 公開鍵 [RFC7250]またはキャッシュ済み 情報拡張 [RFC7924]を使用する場合、このメッセージには 証明書ではなく、サーバーの長期鍵に対応する その他の値が含まれることに注意されたい。[第 4.5.1節

CertificateVerify:

Certificateメッセージ内の公開鍵に対応する秘密鍵を使用した、 ハンドシェイク全体に対する署名。 エンドポイントが証明書による認証を行わない場合、 このメッセージは省略される。[第4.5.2節

Finished:

ハンドシェイク全体に対するMAC(メッセージ認証コード)。 このメッセージは、ハンドシェイクで確立された共有秘密に対する鍵確認を提供し、 エンドポイントの識別情報を交換された鍵に結び付け、 PSKモードではハンドシェイクも認証する。[第 4.5.3節

サーバーのメッセージを受信すると、クライアントは自身の認証 メッセージ、すなわち要求されている場合にはCertificateおよびCertificateVerify、ならびにFinishedで応答する。

この時点でハンドシェイクは完了し、クライアントとサーバーは、 認証付き暗号化によって保護されたアプリケーション層データを交換するために レコード層が必要とする鍵素材を導出する。 第2.3節で規定されている場合を除き、 Finishedメッセージを送信する前にApplication Dataを送信してはならない。 サーバーはクライアントの認証メッセージを受信する前に Application Dataを送信できるが、その時点で送信されるデータは、 当然ながら未認証のピアに送信されることに注意されたい。

2.1. 不正なDHE共有値

クライアントが十分な「key_share」拡張を提供していない場合 (例えば、サーバーが受け入れられない、またはサポートしていない DHEまたはECDHEグループだけが含まれている場合)、サーバーはHelloRetryRequestによって 不一致を修正し、クライアントは図2に示すように、適切な 「key_share」拡張を使用してハンドシェイクを再開する必要がある。 共通の暗号パラメーターをネゴシエートできない場合、 サーバーは適切なアラートによってハンドシェイクを中止しなければならない

      クライアント                                         サーバー

      ClientHello
      + key_share             -------->
                                                HelloRetryRequest
                              <--------               + key_share
      ClientHello
      + key_share             -------->
                                                      ServerHello
                                                      + key_share
                                            {EncryptedExtensions}
                                            {CertificateRequest*}
                                                   {Certificate*}
                                             {CertificateVerify*}
                                                       {Finished}
                              <--------       [Application Data*]
      {Certificate*}
      {CertificateVerify*}
      {Finished}              -------->
      [Application Data]      <------->        [Application Data]
図2: パラメーターが一致しない完全 ハンドシェイクのメッセージフロー

注: ハンドシェイクトランスクリプトには、最初の ClientHello/HelloRetryRequest交換が組み込まれる。新しい ClientHelloによってリセットされることはない。

TLSでは、以下の節で説明するように、 基本ハンドシェイクの最適化された複数の変種も使用できる。

2.2. 再開および 事前共有鍵(PSK)

TLS PSKは外部で確立できるが、 以前の接続でPSKを確立し、 その後、新しい接続を確立するために使用することもできる (PSKによる「セッション再開」または「再開」)。 ハンドシェイクが完了すると、サーバーは、 最初のハンドシェイクから導出された一意の鍵に対応するPSK識別情報を クライアントに送信できる(第4.7.1節を参照)。 その後クライアントは、将来のハンドシェイクでそのPSK識別情報を使用して、 関連付けられたPSKの使用をネゴシエートできる。サーバーがPSKを受け入れた場合、 新しい接続のセキュリティコンテキストは暗号学的に元の接続に結び付けられ、 完全なハンドシェイクの代わりに、最初のハンドシェイクから導出された鍵を使用して 暗号状態を初期化する。 TLS 1.2以前では、この機能は「session IDs」および 「session tickets」[RFC5077]によって提供されていた。 両方の機構はTLS 1.3で廃止される。

PSKは非対称鍵交換とともに使用して、共有鍵と組み合わせて 前方秘匿性を提供することも、単独で使用することもできる。ただし、 単独で使用するとアプリケーションデータの前方秘匿性が失われる。

図3は、 最初のハンドシェイクでPSKを確立し、 2番目のハンドシェイクでそれを使用する一組のハンドシェイクを示している。

       クライアント                                        サーバー

最初のハンドシェイク:
       ClientHello
       + key_share               -------->
                                                       ServerHello
                                                       + key_share
                                             {EncryptedExtensions}
                                             {CertificateRequest*}
                                                    {Certificate*}
                                              {CertificateVerify*}
                                                        {Finished}
                                 <--------     [Application Data*]
       {Certificate*}
       {CertificateVerify*}
       {Finished}                -------->
                                 <--------      [NewSessionTicket]
       [Application Data]        <------->      [Application Data]


後続のハンドシェイク:
       ClientHello
       + key_share*
       + psk_key_exchange_modes
       + pre_shared_key          -------->
                                                       ServerHello
                                                  + pre_shared_key
                                                      + key_share*
                                             {EncryptedExtensions}
                                                        {Finished}
                                 <--------     [Application Data*]
       {Finished}                -------->
       [Application Data]        <------->      [Application Data]
図3: 再開 およびPSKのメッセージフロー

サーバーはPSKによって認証するため、 CertificateまたはCertificateVerifyメッセージを送信しない。クライアントがPSKによる再開を提示する場合、 必要に応じてサーバーが再開を拒否し、 完全なハンドシェイクにフォールバックできるようにするため、 サーバーに「key_share」拡張も提供することが望ましい。 サーバーは「pre_shared_key」拡張で応答してPSK鍵確立の使用をネゴシエートし、 (ここに示すように)「key_share」拡張で応答して非対称鍵確立を行うこともできるため、 前方秘匿性を提供できる。

PSKを外部でプロビジョニングする場合、 PSK識別情報およびPSKとともに使用するKDFハッシュ アルゴリズムもプロビジョニングしなければならない

注: 外部でプロビジョニングされた事前共有秘密を使用する場合、 [RFC4086]で説明されているように、 鍵生成時に十分なエントロピーを使用することが極めて重要である。パスワードまたはその他の 低エントロピー源から共有秘密を導出することは安全ではない。 低エントロピーの秘密またはパスワードは、 PSKバインダーに基づく辞書攻撃を受ける可能性がある。規定されたPSK 認証は、非対称鍵確立とともに使用する場合でも、 強力なパスワードベースの認証付き鍵交換ではない。具体的には、 ハンドシェイクを観測できる攻撃者が、 パスワード/事前共有鍵に対して総当たり攻撃を行うことを防げない。

2.3. 0-RTTデータ

クライアントとサーバーがPSKを共有している場合 (外部から取得したもの、または以前のハンドシェイクによって取得したもの)、 TLS 1.3ではクライアントが最初のフライトでデータ (「早期データ」)を送信できる。クライアントはPSKを使用して サーバーを認証し、早期データを暗号化する。

図4に示すように、 0-RTTデータは、最初のフライトで1-RTT ハンドシェイクに追加されるだけである。ハンドシェイクの残りの部分では、 PSK再開を使用する1-RTTハンドシェイクと同じメッセージを使用する。

      クライアント                                         サーバー

      ClientHello
      + early_data
      + key_share*
      + psk_key_exchange_modes
      + pre_shared_key
      (Application Data*)     -------->
                                                      ServerHello
                                                 + pre_shared_key
                                                     + key_share*
                                            {EncryptedExtensions}
                                                    + early_data*
                                                       {Finished}
                              <--------       [Application Data*]
      (EndOfEarlyData*)
      {Finished}              -------->
      [Application Data]      <------->        [Application Data]

            +  直前に示したメッセージで送信される、
               注目すべき拡張を示す。

            *  常に送信されるとは限らない、任意または
               状況依存のメッセージ/拡張を示す。

            () client_early_traffic_secretから
               導出された鍵を使用して保護されるメッセージを示す。

            {} [sender]_handshake_traffic_secretから
               導出された鍵を使用して保護されるメッセージを示す。

            [] [sender]_application_traffic_secret_Nから
               導出された鍵を使用して保護されるメッセージを示す。
図4: 0-RTT ハンドシェイクのメッセージフロー

重要な注記: 0-RTTデータのセキュリティ特性は、 その他の種類のTLSデータよりも弱い。具体的には、次のとおりである。

  1. プロトコルは、このデータに対して前方秘匿性を保証しない。 前方秘匿性が保証されるかどうか、およびどの保証が適用されるかは、 サーバーの動作によって決まる (第8.1節を参照)。 この動作は、プロトコルの一部としてクライアントに通知されない。 したがって、サーバーの動作について帯域外の知識がない限り、 クライアントはこのデータに前方秘匿性がないものと想定すべきである。

  2. 接続間でリプレイされないことは保証されない。 通常のTLS 1.3 1-RTTデータに対するリプレイ保護は、 サーバーのRandom値によって提供されるが、0-RTTデータは ServerHelloに依存しないため、保証が弱い。この点は、 データがTLSクライアント認証またはアプリケーションプロトコル内で 認証される場合に特に重要である。同じ警告は、 early_exporter_secretのあらゆる使用にも適用される。

0-RTTデータは接続内で複製されることはない (すなわち、サーバーは同じ接続について同じデータを2回処理しない)。 また、攻撃者が0-RTTデータを1-RTTデータであるかのように見せることもできない (異なる鍵で保護されているため)。付録F.5には、 潜在的な攻撃の説明が含まれ、第8節では、 リプレイの影響を制限するためにサーバーが使用できる機構について説明する。

3. 表現言語

本文書は、外部表現におけるデータの書式を扱う。 以下では、極めて基本的で、やや非形式的に定義された表現構文を 使用する。

以下の定義では、この構文の任意の構成要素を 「[[ ]]」(二重角括弧)で囲んで示す。

3.1. 基本ブロックサイズ

すべてのデータ項目の表現は明示的に規定される。基本的なデータ ブロックサイズは1バイト(すなわち8ビット)である。複数バイトのデータ項目は、 左から右、上から下の順にバイトを連結したものである。バイト ストリームから、複数バイトの項目(次の例では数値)を、 C表記を使用して次のように構成する。

   value = (byte[0] << 8*(n-1)) | (byte[1] << 8*(n-2)) |
           ... | byte[n-1];

複数バイト値に対するこのバイト順序は、一般的なネットワークバイト順序、 すなわちビッグエンディアン形式である。

3.2. その他

コメントは「/*」で始まり、「*/」で終わる。

解釈されないデータを含む1バイトのエンティティは、 opaque型である。

既存の型Tに対する型エイリアスT'は、次のように定義する。

   T T';

3.3. 数値

基本的な数値データ型は符号なしバイト(uint8)である。これより大きいすべての数値 データ型は、第3.1節で説明したように 固定長の一連のバイトを連結して構成され、 同様に符号なしである。次の数値 型が事前定義されている。

   uint8 uint16[2];
   uint8 uint24[3];
   uint8 uint32[4];
   uint8 uint64[8];

ここおよび仕様内の他の箇所にあるすべての値は、 ネットワークバイト (ビッグエンディアン)順序で送信される。16進バイト01 02 03 04で表されるuint32は、 10進値16909060に相当する。

3.4. ベクトル

ベクトル(一次元配列)は、同種のデータ要素からなるストリームである。 表現上の目的から、本文書ではベクトルをリストと呼ぶ。 ベクトルのサイズは、文書作成時に指定することも、 実行時まで未指定のままにすることもできる。どちらの場合でも、長さは ベクトル内の要素数ではなく、バイト数を宣言する。型Tの固定長ベクトルである 新しい型T'を指定する構文は、次のとおりである。

   T T'[n];

ここで、T'はデータストリーム内でnバイトを占有し、nはTの サイズ の倍数である。ベクトルの長さは、符号化されたストリームには含まれない。

次の例では、Datumはプロトコルが解釈しない連続する3バイトとして 定義され、Dataは連続する3つのDatumとして定義され、 合計9バイトを消費する。

   opaque Datum[3];      /* 解釈されない3バイト */
   Datum Data[9];        /* 連続する3つの3バイトベクトル */

可変長ベクトルは、<floor..ceiling>という表記を使用して、 有効な長さの部分範囲を両端を含めて指定することで定義する。これらを符号化する場合、 実際の長さがバイトストリーム内でベクトルの内容に先行する。長さは、 ベクトルに指定された最大長(ceiling)を保持するために必要なだけのバイトを 消費する数値の形式になる。実際の長さフィールドが0である 可変長ベクトルを、空のベクトルと呼ぶ。

   T T'<floor..ceiling>;

次の例では、「mandatory」はopaque型のデータを 300バイト以上400バイト以下含まなければならないベクトルである。 空にすることはできない。実際の長さフィールドは、 値400を表すのに十分なuint16である2バイトを消費する (第3.3節を参照)。同様に、「longer」は最大800バイトの データ、すなわち400個のuint16要素を表すことができ、 空であってもよい。その符号化には、ベクトルの先頭に付加された 2バイトの実際の長さフィールドが含まれる。符号化されたベクトルの長さは、 単一要素の長さの正確な倍数でなければならない (例えば、17バイトのuint16ベクトルは不正となる)。

   opaque mandatory<300..400>;
         /* 長さフィールドは2バイトで、空にはできない */
   uint16 longer<0..800>;
         /* 0個から400個までの16ビット符号なし整数 */

3.5. 列挙型

「enum」または 「enumerated」と呼ばれる、追加の疎なデータ型を使用できる。各定義は異なる型である。 同じ型の列挙型だけを代入または比較できる。次の例に示すように、 列挙型の各要素には値を割り当てなければならない。 列挙型の要素には順序がないため、 任意の順序で任意の一意な値を割り当てることができる。

   enum { e1(v1), e2(v2), ... , en(vn) [[, (n)]] } Te;

将来の拡張またはプロトコルへの追加によって、新しい値が定義される場合がある。 フィールドの定義に別段の記載がない限り、実装は 未知の値を解析して無視できる必要がある。

列挙型は、その定義済み序数の最大値が占めるのと同じだけの空間を バイトストリーム内で占有する。次の定義では、 Color型のフィールドの伝送に1バイトが使用される。

   enum { red(3), blue(5), white(7) } Color;

不要な要素を定義せずに幅を強制的に定義するため、 関連付けられたタグを持たない値を任意で指定できる。

次の例では、Tasteはデータストリーム内で2バイトを消費するが、 現在のバージョンのプロトコルでは値1、2、または4だけを取ることができる。

   enum { sweet(1), sour(2), bitter(4), (32000) } Taste;

列挙型の要素名のスコープは、定義された 型内に限定される。 最初の例では、列挙型の2番目の要素への完全修飾参照は Color.blueとなる。代入先が明確に指定されている場合、 このような修飾は不要である。

   Color color = Color.blue;     /* 過剰に指定されているが適正 */
   Color color = blue;           /* 正しく、型は暗黙的 */

列挙型に割り当てられる名前は一意である必要はない。 数値 は、同じ名前が適用される範囲を記述できる。この値には、 その範囲の最小値と最大値を両端を含めて指定し、 2つのピリオド文字で区切る。これは主に、値空間の領域を予約するために有用である。

   enum { sad(0), meh(1..254), happy(255) } Mood;

3.6. 構築型

便宜上、プリミティブ型から構造体型を構築できる。各 指定によって、新しい一意な型が宣言される。定義に使用する構文は、 Cの構文に非常によく似ている。

   struct {
       T1 f1;
       T2 f2;
       ...
       Tn fn;
   } T;

標準的なリスト構文を使用して、固定長および可変長のリスト (ベクトル)フィールドを使用できる。バリアントの例(第3.8節)の構造体V1およびV2がこれを示している。

構造体内のフィールドは、列挙型で使用できるものとよく似た構文で、 型の名前を使用して修飾できる。例えば、T.f2は 前述の宣言の2番目のフィールドを指す。

3.7. 定数

次のように、「=」を使用してフィールドおよび変数に固定値を割り当てることができる。

   struct {
       T1 f1 = 8;  /* T.f1は常に8でなければならない */
       T2 f2;
   } T;

3.8. バリアント

定義された構造体は、環境内で利用可能な 何らかの情報に基づくバリアントを持つことができる。セレクターは、 構造体が定義する可能なバリアントを定義する列挙 型でなければならない。selectの各分岐(以下)は、 そのバリアントのフィールドの型と、任意のフィールドラベルを指定する。 実行時にバリアントを選択する機構は、 表現言語では規定されない。

   struct {
       T1 f1;
       T2 f2;
       ....
       Tn fn;
       select (E) {
           case e1: Te1 [[fe1]];
           case e2: Te2 [[fe2]];
           ....
           case en: Ten [[fen]];
       };
   } Tv;

例を次に示す。

   enum { apple(0), orange(1) } VariantTag;

   struct {
       uint16 number;
       opaque string<0..10>; /* 可変長 */
   } V1;

   struct {
       uint32 number;
       opaque string[10];    /* 固定長 */
   } V2;

   struct {
       VariantTag type;
       select (VariantRecord.type) {
           case apple:  V1;
           case orange: V2;
       };
   } VariantRecord;

4. ハンドシェイクプロトコル

ハンドシェイクプロトコルは、接続のセキュリティパラメーターを ネゴシエートするために使用される。ハンドシェイクメッセージはTLSレコード層に渡され、 そこで1つ以上のTLSPlaintextまたはTLSCiphertext構造体内にカプセル化され、 現在アクティブな接続状態で規定されているとおりに処理および送信される。

   enum {
       client_hello(1),
       server_hello(2),
       new_session_ticket(4),
       end_of_early_data(5),
       encrypted_extensions(8),
       certificate(11),
       certificate_request(13),
       certificate_verify(15),
       finished(20),
       key_update(24),
       message_hash(254),
       (255)
   } HandshakeType;

   struct {
       HandshakeType msg_type;    /* ハンドシェイクの種類 */
       uint24 length;             /* メッセージ内の残りのバイト数 */
       select (Handshake.msg_type) {
           case client_hello:          ClientHello;
           case server_hello:          ServerHello;
           case end_of_early_data:     EndOfEarlyData;
           case encrypted_extensions:  EncryptedExtensions;
           case certificate_request:   CertificateRequest;
           case certificate:           Certificate;
           case certificate_verify:    CertificateVerify;
           case finished:              Finished;
           case new_session_ticket:    NewSessionTicket;
           case key_update:            KeyUpdate;
       };
   } Handshake;

TLS拡張によって変更されない限り、プロトコルメッセージは、 第4.1節で定義され、 第2節の図に示されている順序で 送信しなければならない。 予期しない順序でハンドシェイクメッセージを受信したピアは、 「unexpected_message」アラートによってハンドシェイクを 中止しなければならない

新しいハンドシェイクメッセージの種類は、 第11節で説明されているようにIANAによって割り当てられる。

4.1. トランスクリプトハッシュ

TLSにおける多くの暗号学的計算では、トランスクリプト ハッシュを使用する。この値は、含まれる各ハンドシェイクメッセージを 連結したものをハッシュすることで計算される。これには、ハンドシェイク メッセージの種類および長さフィールドを搬送するメッセージヘッダーが含まれるが、 レコード層ヘッダーは含まれない。すなわち、

 Transcript-Hash(M1, M2, ... Mn) = Hash(M1 || M2 || ... || Mn)

この一般規則の例外として、サーバーがClientHelloに HelloRetryRequestで応答する場合、ClientHello1の値は、 Hash(ClientHello1)を含む、ハンドシェイクの種類が 「message_hash」(254)である特別な合成ハンドシェイクメッセージに置き換えられる。すなわち、

 Transcript-Hash(ClientHello1, HelloRetryRequest, ... Mn) =
     Hash(message_hash ||        /* ハンドシェイクの種類 */
          00 00 Hash.length  ||  /* ハンドシェイクメッセージの長さ(バイト) */
          Hash(ClientHello1) ||  /* ClientHello1のハッシュ */
          HelloRetryRequest  || ... || Mn)

この構成を使用する理由は、サーバーが ClientHello1のハッシュだけをCookieに格納することで、 中間ハッシュ状態全体をエクスポートする必要なく、 ステートレスなHelloRetryRequestを実行できるようにするためである(第4.3.2節を参照)。

メッセージの範囲が「...」で指定されている場合、トランスクリプトハッシュは、 メインハンドシェイク中に送信または受信された一連のハンドシェイクメッセージのうち、 指定されたメッセージから開始し、指定されたメッセージで終了する範囲から取得される。 本文書では、次の一連のハンドシェイク メッセージ(一部は省略される場合がある)から取得される: ClientHello、HelloRetryRequest、ClientHello、 ServerHello、 EncryptedExtensions、サーバーのCertificateRequest、サーバーのCertificate、 サーバーのCertificateVerify、サーバーのFinished、EndOfEarlyData、クライアントの Certificate、クライアントのCertificateVerify、およびクライアントのFinished。TLS拡張によって メッセージが追加または削除される場合があり、その場合、トランスクリプトハッシュには 変更後のシーケンスが反映される。

一般に、実装はServerHelloでハッシュが選択された後、 ネゴシエートされたハッシュに基づく実行中の トランスクリプトハッシュ値を保持することで実装できる。

ただし、後続のハンドシェイク後認証には 相互のメッセージは含まれず、メイン ハンドシェイクの終了までのメッセージだけが含まれることに注意されたい。

4.2. 鍵交換メッセージ

鍵交換メッセージは、クライアントおよびサーバーのセキュリティ能力を 判定し、ハンドシェイクの残りとデータを保護するために使用する トラフィック鍵を含む共有秘密を確立するために使用される。

4.2.1. 暗号 ネゴシエーション

TLSでは、クライアントが ClientHelloで次の4つの選択肢群を 提示することで暗号ネゴシエーションが進行する。

  • クライアントがサポートするAEAD アルゴリズム/HKDFハッシュの ペアを示す暗号スイートの一覧。

  • クライアントがサポートする 鍵交換グループを示す「supported_groups」(第4.3.7節)拡張、および これらのグループの一部または全部について鍵交換共有値を含む 「key_share」(第4.3.8節)拡張。「groups」という用語は 歴史的なものであり、非DHE鍵確立アルゴリズムをサポートしていなかった TLS 1.3の初期版に由来する。

  • クライアントが受け入れ可能な署名 アルゴリズムを示す「signature_algorithms」(第4.3.3節) 拡張。証明書固有の署名アルゴリズムを示すために、 「signature_algorithms_cert」拡張 (第4.3.3節) も追加できる。

  • クライアントが既知である対称鍵の識別情報の一覧を含む 「pre_shared_key」(第4.3.11節)拡張、および PSKとともに使用できる鍵交換モードを示す 「psk_key_exchange_modes」(第4.3.9節) 拡張。

サーバーがPSKを選択しない場合、これらの選択肢の最初の3つは 完全に直交している。サーバーは、 暗号スイート、鍵確立用の非対称鍵交換グループおよび鍵共有、 ならびにクライアントに対して自身を認証するための署名アルゴリズム/証明書のペアを それぞれ独立して選択する。受信した「supported_groups」と サーバーがサポートするグループとの間に共通部分がない場合、 サーバーは「handshake_failure」または「insufficient_security」アラートによって ハンドシェイクを中止しなければならない

サーバーがPSKを選択する場合、 クライアントの「psk_key_exchange_modes」拡張が示す一覧から 鍵確立モード (現時点では、PSK単独または非対称鍵交換との組み合わせ)も 選択しなければならない。PSKを非対称鍵交換なしで使用できる場合、 前段落で説明した非PSKの場合とは異なり、 「supported_groups」パラメーターに共通部分がなくても必ずしも致命的ではないことに注意されたい。

サーバーが非対称鍵交換グループを選択し、 クライアントが最初のClientHelloで 互換性のある「key_share」拡張を提示しなかった場合、サーバーは HelloRetryRequest(第4.2.4節)メッセージで 応答しなければならない

サーバーがパラメーターを正常に選択し、 HelloRetryRequestを必要としない場合、選択したパラメーターをServerHelloで 次のように示す。

  • PSKを使用する場合、サーバーは 選択した鍵を示す「pre_shared_key」拡張を送信する。

  • 非対称鍵交換を使用する場合、サーバーは 「key_share」拡張も提供する。PSKを使用しない場合、 非対称鍵交換および証明書ベースの 認証が常に使用される。

  • 証明書によって認証する場合、サーバーは Certificate(第 4.5.1節)およびCertificateVerify (第4.5.2節) メッセージを送信する。本文書で定義するTLS 1.3では、 PSKまたは証明書のいずれか一方を常に使用するが、 両方を使用することはない。将来の文書で、 これらを併用する方法が定義される場合がある。

サーバーがサポートされるパラメーター群をネゴシエートできない場合 (すなわち、クライアントとサーバーのパラメーターに共通部分がない場合)、 「handshake_failure」または「insufficient_security」の致命的アラートによって ハンドシェイクを中止しなければならない第6節を参照)。

4.2.2. Client Hello

クライアントが初めてサーバーに接続するとき、 最初のTLSメッセージとして ClientHelloを送信することが要求される。サーバーがClientHelloに HelloRetryRequestで応答した場合も、クライアントは ClientHelloを送信する。その場合、クライアントは 次に示す変更を除き、同じ ClientHelloを変更せずに送信しなければならない

  • HelloRetryRequestで「key_share」拡張が 提供された場合、 共有値の一覧を、指定されたグループの単一の KeyShareEntryを含む一覧に置き換える。

  • 「early_data」拡張(第4.3.10節)が 存在していた場合、それを削除する。HelloRetryRequestの後では、 早期データは許可されない。

  • HelloRetryRequestで提供された場合、 「cookie」拡張を含める。

  • 存在する場合は、「obfuscated_ticket_age」および バインダー値を再計算し、 サーバーが示した暗号スイートと互換性のない PSKを任意で削除することにより、 「pre_shared_key」拡張を更新する。

  • 「padding」拡張 [RFC7685]を 任意で追加、削除、または長さを変更する。

  • 将来定義され、HelloRetryRequestに存在する 拡張によって許可される可能性があるその他の変更。

TLS 1.3では再ネゴシエーションが禁止されているため、 サーバーがTLS 1.3をネゴシエートした後、その他の時点でClientHelloを受信した場合、 「unexpected_message」アラートによって 接続を終了しなければならない

サーバーが以前のバージョンの TLSでTLS接続を確立し、 再ネゴシエーション中にTLS 1.3 ClientHelloを受信した場合、 以前のプロトコルバージョンを維持しなければならない。特に、TLS 1.3を ネゴシエートしてはならない

このメッセージの構造は次のとおりである。

   uint16 ProtocolVersion;
   opaque Random[32];

   uint8 CipherSuite[2];    /* 暗号スイートセレクター */

   struct {
       ProtocolVersion legacy_version = 0x0303;    /* TLS v1.2 */
       Random random;
       opaque legacy_session_id<0..32>;
       CipherSuite cipher_suites<2..2^16-2>;
       opaque legacy_compression_methods<1..2^8-1>;
       Extension extensions<7..2^16-1>;
   } ClientHello;
legacy_version:

以前のバージョンのTLSでは、このフィールドは バージョンネゴシエーションに使用され、 クライアントがサポートする最も高いバージョン番号を表していた。 多くのサーバーがバージョンネゴシエーションを適切に実装しておらず、 サーバーがサポートするバージョンより高いバージョン番号を持つ、 本来なら受け入れ可能なClientHelloを拒否する 「version intolerance」が生じることが経験上判明している。 TLS 1.3では、クライアントは 「supported_versions」拡張(第4.3.1節)でバージョンの選好を示し、 legacy_versionフィールドは TLS 1.2のバージョン番号である0x0303に 設定しなければならない。 TLS 1.3 ClientHelloは、 legacy_versionが0x0303であり、supported_versions拡張が存在し、 その中で示される最も高いバージョンが0x0304であることによって識別される。 (後方互換性の詳細については、付録E を参照。) 0x0303と等しくないlegacy_version値を受信したサーバーは、 「protocol_version」アラートによって ハンドシェイクを中止しなければならない

random:

安全な乱数生成器によって生成された32バイト。 詳細については、付録C を参照されたい。

legacy_session_id:

TLS 1.3より前のバージョンのTLSは、 このバージョンでは事前共有鍵と統合された 「セッション再開」機能をサポートしていた (第2.2節を参照)。 TLS 1.3より前のサーバーによって設定されたキャッシュ済みセッションIDを 持つクライアントは、このフィールドを その値に設定することが望ましい。 互換モード(付録 E.4を参照)では、このフィールドは空で あってはならないため、 TLS 1.3より前のセッションを提示しないクライアントは、 新しい32バイト値を 生成しなければならない。 この値はランダムである必要はないが、 実装が特定の値に固定されること (ossificationとも呼ばれる)を避けるため、 予測不能であることが望ましい。 それ以外の場合、この値は長さ0の一覧 (すなわち、値が0である1バイトの長さフィールド)に 設定しなければならない

cipher_suites:

クライアントがサポートする対称暗号の選択肢、 具体的にはレコード保護アルゴリズム (秘密鍵の長さを含む)およびHKDFで使用するハッシュの一覧。 クライアントの選好順に降順で並べられる。値は付録B.4で定義される。 一覧にサーバーが認識、サポート、または使用を希望しない 暗号スイートが含まれている場合、サーバーは それらの暗号スイートを無視しなければならず、 残りを通常どおり処理する。 クライアントがPSK鍵確立を試みる場合、 PSKに関連付けられたHashを示す暗号スイートを 少なくとも1つ広告することが望ましい

legacy_compression_methods:

TLS 1.3より前のバージョンは圧縮をサポートし、 サポートされる圧縮方式の一覧がこのフィールドで送信されていた。 すべてのTLS 1.3 ClientHelloで、この一覧は、 以前のバージョンのTLSにおける「null」圧縮方式に対応する 0に設定された正確に1バイトを 含まなければならない。 このフィールドにその他の値を持つTLS 1.3 ClientHelloを 受信した場合、サーバーは 「illegal_parameter」アラートによってハンドシェイクを 中止しなければならない。 TLS 1.3サーバーは、その他の圧縮方式を含む TLS 1.2以前のClientHelloを受信する場合があり、 そのような以前のバージョンをネゴシエートする場合は、 適切な以前のバージョンのTLSの手順に 従わなければならないことに注意されたい。

extensions:

クライアントは、extensionsフィールドで データを送信することにより、 サーバーに拡張機能を要求する。実際の「Extension」形式は 第4.3節で定義される。 TLS 1.3では、 以前のバージョンのTLSとのClientHelloの互換性を維持するために 機能が拡張へ移されたため、特定の拡張の使用は必須である。 サーバーは認識できない拡張を 無視しなければならない

すべてのバージョンのTLSでは、 compression_methodsフィールドの後にextensionsフィールドを任意で続けることができる。 TLS 1.3 ClientHello メッセージは常に拡張を含む (最低限「supported_versions」を含む。そうでなければ、 TLS 1.2 ClientHelloメッセージとして解釈される)。 ただし、TLS 1.3サーバーは以前のバージョンのTLSから、 extensionsフィールドを持たないClientHelloメッセージを受信する場合がある。 拡張の存在は、ClientHello末尾の compression_methodsフィールドの後にバイトが存在するかどうかを 判定することで検出できる。この任意データの検出方法は、 可変長フィールドを使用する通常のTLSの方法とは異なるが、 拡張が定義される前のTLSとの互換性のために使用されることに注意されたい。 TLS 1.3サーバーは、最初にこの確認を行い、 「supported_versions」拡張が存在する場合に限り、 TLS 1.3のネゴシエーションを試みる必要がある。 TLS 1.3より前のバージョンのTLSをネゴシエートする場合、 サーバーは、 メッセージがlegacy_compression_methodsの後にデータを含まないか、 後続データのない有効なextensionsブロックを含むことを 確認しなければならない。 そうでない場合、「decode_error」アラートによって ハンドシェイクを中止しなければならない

クライアントが拡張を使用して追加機能を要求し、 サーバーがその機能を提供しない場合、 クライアントはハンドシェイクを 中止してもよい

ClientHelloメッセージを送信した後、クライアントは ServerHello またはHelloRetryRequestメッセージを待機する。早期データを 使用する場合、クライアントは早期Application Data (第2.3節)を、 次のハンドシェイクメッセージを待機している間に送信してもよい。

4.2.3. Server Hello

サーバーは、ClientHelloに基づいて受け入れ可能な ハンドシェイクパラメーター群をネゴシエートできる場合、 ハンドシェイクを続行するため、ClientHelloメッセージに応答して このメッセージを送信する。

このメッセージの構造は次のとおりである。

   struct {
       ProtocolVersion legacy_version = 0x0303;    /* TLS v1.2 */
       Random random;
       opaque legacy_session_id_echo<0..32>;
       CipherSuite cipher_suite;
       uint8 legacy_compression_method = 0;
       Extension extensions<6..2^16-1>;
   } ServerHello;
legacy_version:

以前のバージョンのTLSでは、このフィールドは バージョンネゴシエーションに使用され、 接続に対して選択されたバージョン番号を表していた。残念ながら、 新しい値を提示すると動作しないミドルボックスが存在する。 TLS 1.3では、TLSサーバーは 「supported_versions」拡張(第4.3.1節)を使用して バージョンを示し、legacy_versionフィールドは TLS 1.2のバージョン番号である0x0303に 設定しなければならない。 (後方互換性の詳細については、付録E を参照。) 0x0303と等しくないlegacy_version値を持つ TLS 1.3 Server Helloを受信したクライアントは、 「protocol_version」アラートによって ハンドシェイクを中止しなければならない

random:

安全な乱数生成器によって生成された32バイト。 詳細については、付録C を参照されたい。 TLS 1.2またはTLS 1.1をネゴシエートする場合、 最後の8バイトは以下で説明するように 上書きしなければならないが、 残りのバイトはランダムでなければならない。 この構造体はサーバーによって生成され、 ClientHello.randomとは独立して 生成しなければならない

legacy_session_id_echo:

クライアントのlegacy_session_idフィールドの内容。 クライアントの値が、 サーバーが再開しないことを選択した、キャッシュ済みの TLS 1.3より前のセッションに対応する場合でも、 このフィールドはエコーされることに注意されたい。 ClientHelloで送信したものと一致しない legacy_session_id_echoフィールドを受信したクライアントは、 「illegal_parameter」アラートによって ハンドシェイクを中止しなければならない

cipher_suite:

ClientHello.cipher_suitesの 一覧からサーバーが選択した単一の暗号スイート。 提示していない暗号スイートを受信したクライアントは、 「illegal_parameter」アラートによって ハンドシェイクを中止しなければならない

legacy_compression_method:

値が0で なければならない単一のバイト。 このフィールドにその他の値を持つTLS 1.3 ServerHelloを 受信した場合、クライアントは 「illegal_parameter」アラートによって ハンドシェイクを中止しなければならない

extensions:

拡張の一覧。ServerHelloには、 暗号コンテキストの確立および プロトコルバージョンのネゴシエーションに必要な拡張だけを 含めなければならない。 すべてのTLS 1.3 ServerHelloメッセージは、 「supported_versions」拡張を 含まなければならない。 現在のServerHelloメッセージには、さらに 「pre_shared_key」拡張または「key_share」拡張のいずれか、 またはその両方 (非対称鍵確立とともにPSKを使用する場合)が含まれる。 その他の拡張(第4.3節を参照)は、 EncryptedExtensionsメッセージで別途送信される。

ミドルボックスとの後方互換性のため (付録E.4を参照)、 HelloRetryRequest メッセージはServerHelloと同じ構造体を使用するが、 Randomは「HelloRetryRequest」の SHA-256である次の特別な値に設定される。

  CF 21 AD 74 E5 9A 61 11 BE 1D 8C 02 1E 65 B8 91
  C2 A2 11 16 7A BB 8C 5E 07 9E 09 E2 C8 A8 33 9C

server_hello型のメッセージを受信した場合、 実装は最初にRandom値を調べ、この値と一致する場合、 第4.2.4節で説明されているとおりに 処理しなければならない

TLS 1.3には、サーバーの random値に埋め込まれたダウングレード保護機構がある。 ClientHelloに応答してTLS 1.2以前をネゴシエートする TLS 1.3サーバーは、ServerHello内のRandom値の最後の8バイトを 特別な値に設定しなければならない

TLS 1.2をネゴシエートする場合、TLS 1.3サーバーは Random値の最後の8バイトを 次のバイト列に設定しなければならない

  44 4F 57 4E 47 52 44 01

[RFC8996]および 付録E.5は、 TLS 1.2より前のTLSバージョンの ネゴシエーションを禁止している。ただし、その指針に従わない サーバー実装は、 ServerHello.random値の最後の8バイトを 次のバイト列に設定しなければならない

  44 4F 57 4E 47 52 44 00

TLS 1.2以前を示すServerHelloを受信したTLS 1.3クライアントは、 最後の8バイトがこれらの値のいずれとも等しくないことを 確認しなければならない。 TLS 1.2クライアントも、ServerHelloがTLS 1.1以前を示す場合、 最後の8バイトが 2番目の値と等しくないことを確認することが望ましい。 一致が見つかった場合、クライアントは 「illegal_parameter」アラートによってハンドシェイクを 中止しなければならない。 この機構は、Finished交換が提供する保護に加えて、 ダウングレード攻撃に対する限定的な保護を提供する。 TLS 1.2以前に存在するメッセージであるServerKeyExchangeは、 両方のrandom値に対する署名を含むため、 一時暗号を使用する限り、能動的攻撃者が検出されずに random値を変更することはできない。 静的RSAを使用する場合、この機構はダウングレード保護を提供しない。

注: これは[RFC5246]からの変更であるため、実際には多くの TLS 1.2クライアントおよびサーバーは、 上記で規定したとおりには動作しない。

TLS 1.2以前で再ネゴシエーションを実行する レガシーTLSクライアントが、再ネゴシエーション中に TLS 1.3 ServerHelloを受信した場合、 「protocol_version」アラートによってハンドシェイクを 中止しなければならない。 TLS 1.3がネゴシエートされた場合、 再ネゴシエーションは不可能であることに注意されたい。

4.2.4. Hello Retry Request

サーバーは、受け入れ可能なパラメーター群を見つけることはできるが、 ClientHelloにハンドシェイクを続行するための十分な情報が 含まれていない場合、ClientHelloメッセージに応答して このメッセージを送信する。第4.2.3節で説明したように、 HelloRetryRequestはServerHelloメッセージと同じ形式を持ち、 legacy_version、legacy_session_id_echo、cipher_suite、および legacy_compression_methodフィールドは同じ意味を持つ。 ただし、便宜上、本文書では「HelloRetryRequest」を 個別のメッセージであるかのように説明する。

サーバーの拡張は「supported_versions」を 含まなければならない。 さらに、クライアントが正しいClientHelloの組を生成するために 必要な最小限の拡張群を 含むことが望ましい。 HelloRetryRequestには、任意の「cookie」 (第4.3.2節を参照) 拡張を除き、クライアントがClientHelloで最初に提示していない 拡張を含めてはならない

HelloRetryRequestを受信した場合、クライアントは、 第4.2.3節で規定されているとおり、 legacy_version、legacy_session_id_echo、cipher_suite、 およびlegacy_compression_methodを 確認しなければならず、 その後、「supported_versions」を使用したバージョンの判定から始めて、 拡張を処理する。 HelloRetryRequestによってClientHelloに何の変更も生じない場合、 クライアントは「illegal_parameter」アラートによって ハンドシェイクを中止しなければならない。 同じ接続で2番目のHelloRetryRequestを受信した場合 (すなわち、ClientHello自体がHelloRetryRequestへの応答であった場合)、 「unexpected_message」アラートによってハンドシェイクを 中止しなければならない

それ以外の場合、クライアントはHelloRetryRequest内の すべての拡張を処理しなければならず、 更新された2番目のClientHelloを送信しなければならない。 本仕様で定義されるHelloRetryRequest拡張は次のとおりである。

提示していない暗号スイートを受信したクライアントは、 ハンドシェイクを中止しなければならない。 サーバーは、適合する更新済みClientHelloを受信した場合、 同じ暗号スイートをネゴシエートすることを 保証しなければならない (サーバーがネゴシエーションの最初の手順として暗号スイートを選択する場合、 これは自動的に行われる)。 ServerHelloを受信した場合、クライアントは、ServerHelloで提供された 暗号スイートがHelloRetryRequest内のものと同じであることを 確認しなければならず、そうでない場合は 「illegal_parameter」アラートによってハンドシェイクを中止しなければならない。

さらに、更新されたClientHelloで、クライアントは、 選択された暗号スイートのハッシュ以外に関連付けられた 事前共有鍵を提示しないことが望ましい。 これにより、クライアントは2番目のClientHelloで複数のハッシュについて 部分的なハッシュトランスクリプトを計算する必要を回避できる。

HelloRetryRequestの「supported_versions」拡張内の selected_versionの値はServerHelloで 維持しなければならず、 値が変更された場合、クライアントは「illegal_parameter」アラートによって ハンドシェイクを中止しなければならない

4.3. 拡張

多くのTLSメッセージには、タグ・長さ・値形式で符号化された 拡張構造体が含まれる。

   struct {
       ExtensionType extension_type;
       opaque extension_data<0..2^16-1>;
   } Extension;

   enum {
       server_name(0),                             /* RFC 6066, 9261 */
       status_request(5),                          /* RFC 6066, 9846 */
       supported_groups(10),                       /* RFC 7919, 9846 */
       signature_algorithms(13),                   /* RFC 9846 */
       use_srtp(14),                               /* RFC 5764 */
       heartbeat(15),                              /* RFC 6520 */
       application_layer_protocol_negotiation(16), /* RFC 7301 */
       client_certificate_type(19),                /* RFC 7250 */
       server_certificate_type(20),                /* RFC 7250 */
       padding(21),                                /* RFC 7685 */
       compress_certificate(27),                   /* RFC 8879 */
       record_size_limit(28),                      /* RFC 8449 */
       delegated_credential(34),                   /* RFC 9345 */
       supported_ekt_ciphers(39),                  /* RFC 8870 */
       pre_shared_key(41),                         /* RFC 9846 */
       early_data(42),                             /* RFC 9846 */
       supported_versions(43),                     /* RFC 9846 */
       cookie(44),                                 /* RFC 9846 */
       psk_key_exchange_modes(45),                 /* RFC 9846 */
       certificate_authorities(47),                /* RFC 9846 */
       oid_filters(48),                            /* RFC 9846 */
       post_handshake_auth(49),                    /* RFC 9846 */
       signature_algorithms_cert(50),              /* RFC 9846 */
       key_share(51),                              /* RFC 9846 */
       transparency_info(52),                      /* RFC 9162 */
       external_id_hash(55),                       /* RFC 8844 */
       external_session_id(56),                    /* RFC 8844 */
       quic_transport_parameters(57),              /* RFC 9001 */
       ticket_request(58),                         /* RFC 9149 */
       ech_outer_extensions(64768),                /* RFC 9849 */
       encrypted_client_hello(65037),              /* RFC 9849 */
       (65535)
   } ExtensionType;

注: この一覧には、本文書の執筆時点で 「Recommended」とされ、TLS 1.3で許可されている拡張だけが含まれる。

各フィールドの意味は次のとおりである。

  • 「extension_type」は、特定の拡張の種類を識別する。

  • 「extension_data」は、特定の拡張の種類に固有の 情報を含む。

「extension_data」フィールドの内容は通常、 TLS表現言語で定義された拡張固有の構造体によって定義される。 別段の規定がない限り、末尾データは禁止される。すなわち、送信者は 「extension_data」フィールド内の構造体の後にデータを 含めてはならない。 拡張を処理する際、構造体を解析した後にデータが残っている場合、 受信者は「decode_error」アラートによってハンドシェイクを 中止しなければならない。 受信者が拡張を実装していない場合、または拡張を無視するよう設定されている場合、 これは適用されない。

拡張の種類の一覧は、第11節で説明されているようにIANAによって管理される。

拡張は一般に要求/応答形式で構成されるが、 対応する応答を持たない要求だけの拡張 (すなわち、指示)もある。クライアントはClientHelloメッセージで 拡張要求を送信し、サーバーはServerHello、EncryptedExtensions、 HelloRetryRequest、およびCertificateメッセージで 拡張応答を送信する。サーバーはCertificateRequestメッセージで 拡張要求を送信し、クライアントはCertificateメッセージで 応答してもよい。 サーバーはNewSessionTicketで要求されていない拡張を 送信してもよいが、 クライアントはこれらに直接応答しない。

HelloRetryRequest内の「cookie」拡張を除き、 リモートエンドポイントが対応する拡張要求を送信していない場合、 実装は拡張応答 (すなわち、ServerHello、EncryptedExtensions、HelloRetryRequest、 およびCertificateメッセージ内の拡張)を 送信してはならない。 そのような拡張を受信した場合、エンドポイントは 「unsupported_extension」アラートによってハンドシェイクを 中止しなければならない

以下の表は、指定された拡張が出現できるメッセージを、 次の表記を使用して示している: CH(ClientHello)、SH (ServerHello)、EE(EncryptedExtensions)、CT(Certificate)、CR (CertificateRequest)、NST(NewSessionTicket)、およびHRR (HelloRetryRequest)。実装が認識できる拡張を、 その拡張に対して指定されていないメッセージ内で受信した場合、 「illegal_parameter」アラートによってハンドシェイクを 中止しなければならない

表1: TLS拡張
拡張 TLS 1.3
server_name [RFC6066] [RFC9261] CH, EE, CR
status_request [RFC6066] [RFC9846] CH, CR, CT
supported_groups [RFC7919] [RFC9846] CH, EE
signature_algorithms [RFC9846] CH, CR
use_srtp [RFC5764] CH, EE
heartbeat [RFC6520] CH, EE
application_layer_protocol_negotiation [RFC7301] CH, EE
client_certificate_type [RFC7250] CH, EE
server_certificate_type [RFC7250] CH, EE
padding [RFC7685] CH
compress_certificate [RFC8879] CH, CR
record_size_limit [RFC8449] CH, EE
delegated_credential [RFC9345] CH, CR, CT
supported_ekt_ciphers [RFC8870] CH, EE
pre_shared_key [RFC9846] CH, SH
early_data [RFC9846] CH, EE, NST
supported_versions [RFC9846] CH, SH, HRR
cookie [RFC9846] CH, HRR
psk_key_exchange_modes [RFC9846] CH
certificate_authorities [RFC9846] CH, CR
oid_filters [RFC9846] CR
post_handshake_auth [RFC9846] CH
signature_algorithms_cert [RFC9846] CH, CR
key_share [RFC9846] CH, SH, HRR
transparency_info [RFC9162] CH, CR, CT
external_id_hash [RFC8844] CH, EE
external_session_id [RFC8844] CH, EE
quic_transport_parameters [RFC9001] CH, EE
ticket_request [RFC9149] CH, EE
ech_outer_extensions [RFC9849] CH
encrypted_client_hello [RFC9849] CH, HRR, EE

注: この表には、本文書の執筆時点で 「Recommended」とされ、TLS 1.3で許可されている拡張だけが含まれる。

異なる種類の複数の拡張が存在する場合、 拡張は任意の順序で出現してもよい。 ただし、「pre_shared_key」(第 4.3.11節)は、ClientHello内の最後の拡張で なければならない (ただし、ServerHelloのextensionsブロック内では任意の場所に出現できる)。 指定されたextensionブロック内に、 同じ種類の拡張が複数存在してはならない

TLS 1.2とは異なり、TLS 1.3では、 再開PSKモードであっても、各ハンドシェイクで拡張がネゴシエートされる。 ただし、0-RTTパラメーターは以前のハンドシェイクでネゴシエートされたものであり、 不一致がある場合、0-RTTを拒否する必要が生じることがある (第 4.3.10節を参照)。

このプロトコルでは、新しい機能と既存の機能との間に、 全体的なセキュリティを大幅に低下させる可能性がある、 微妙な(またはそれほど微妙でない)相互作用が生じる場合がある。 新しい拡張を設計する際は、次の考慮事項を 考慮すべきである。

  • サーバーが拡張に同意しない場合の一部は エラー状態 (例えば、ハンドシェイクを続行できない場合)であり、 一部は特定の機能のサポートを拒否するだけである。 一般に、前者にはエラーアラートを使用し、 後者にはサーバー拡張応答内のフィールドを使用すべきである。

  • 拡張は、可能な限り、 ハンドシェイクメッセージの操作によって特定の機能の使用 (または不使用)を強制する攻撃を防止するよう設計すべきである。 この原則は、その機能がセキュリティ上の問題を引き起こすと 考えられているかどうかにかかわらず従うべきである。 多くの場合、拡張フィールドがFinishedメッセージのハッシュへの入力に 含まれるという事実だけで十分であるが、 拡張がハンドシェイク段階で送信されるメッセージの意味を変更する場合は、 細心の注意が必要である。 設計者および実装者は、ハンドシェイクが認証されるまで、 能動的攻撃者がメッセージを変更し、 拡張を挿入、削除、または置換できることを認識すべきである。

4.3.1. サポートされるバージョン

   struct {
       select (Handshake.msg_type) {
           case client_hello:
                ProtocolVersion versions<2..254>;

           case server_hello: /* およびHelloRetryRequest */
                ProtocolVersion selected_version;
       };
   } SupportedVersions;

「supported_versions」拡張は、 クライアントがサポートするTLSのバージョンを示し、 サーバーが使用するバージョンを示すために使用される。 この拡張には、選好順に並べられたサポートされるバージョンの一覧が含まれ、 最も優先されるバージョンが先頭に置かれる。 本仕様の実装は、ネゴシエートする用意があるすべてのTLSバージョンを含む この拡張をClientHelloで 送信しなければならない (本仕様では最低限0x0304を意味するが、以前のバージョンのTLSの ネゴシエーションを許可する場合、それらも 存在しなければならない)。

この拡張が存在しない場合、本仕様に適合し、 TLS 1.2もサポートするサーバーは、 ClientHello.legacy_versionが0x0304以降であっても、 [RFC5246]で規定されているとおり、 TLS 1.2以前をネゴシエートしなければならない。 サーバーは、legacy_versionが0x0304以降のClientHelloを受信した場合、 ハンドシェイクを中止してもよい

この拡張がClientHelloに存在する場合、サーバーは バージョンネゴシエーションにClientHello.legacy_version値を 使用してはならず、 クライアントの選好を判定するために 「supported_versions」拡張だけを 使用しなければならない。 サーバーは、その拡張内に存在するTLSバージョンだけを 選択しなければならず、 その拡張内に存在する未知のバージョンを 無視しなければならない。 一方が疎な範囲をサポートする場合、この機構によって TLS 1.2より前のバージョンをネゴシエートできることに注意されたい。 以前のバージョンのTLSをサポートすることを選択するTLS 1.3実装は、 TLS 1.2をサポートすることが望ましい。 サーバーは、この拡張を含むがバージョン一覧に0x0304を含まない ClientHelloを受信する用意が なければならない

TLS 1.3より前のバージョンをネゴシエートするサーバーは、 ServerHello.versionを設定し、 「supported_versions」拡張を 送信してはならない。 TLS 1.3をネゴシエートするサーバーは、 選択されたバージョン値(0x0304)を含む 「supported_versions」拡張を送信して 応答しなければならない。 ServerHello.legacy_versionフィールドを 0x0303(TLS 1.2)に設定 しなければならない

サーバーのハンドシェイクメッセージがServerHelloか HelloRetryRequestかを判定するためにServerHello.randomを確認した後、 クライアントはServerHelloの残りを処理する前に この拡張を確認しなければならない。 そのためには、クライアントがServerHelloを解析して拡張を読み取る必要がある。 この拡張が存在する場合、クライアントは ServerHello.legacy_version値を 無視しなければならず、 選択されたバージョンを判定するために 「supported_versions」拡張だけを 使用しなければならない。 ServerHello内の「supported_versions」拡張に、 クライアントが提示していないバージョン、またはTLS 1.3より前のバージョンが 含まれている場合、クライアントは「illegal_parameter」アラートによって ハンドシェイクを中止しなければならない

4.3.3. 署名 アルゴリズム

TLS 1.3は、デジタル署名で使用できる 署名アルゴリズムを示す2つの拡張を提供する。 「signature_algorithms_cert」拡張は証明書内の署名に適用され、 TLS 1.2で最初に導入された「signature_algorithms」拡張は、 CertificateVerifyメッセージ内の署名に適用される。 証明書内の鍵も、それとともに使用される署名アルゴリズムに対して 適切な種類でなければならない。 以下で説明するように、これはRSA鍵およびPSS署名において 特に問題となる。 「signature_algorithms_cert」拡張が存在しない場合、 「signature_algorithms」拡張は証明書内に現れる署名にも適用される。 サーバーが証明書によって自身を認証することを望むクライアントは、 「signature_algorithms」拡張を 送信しなければならない。 サーバーが証明書によって認証しようとしているにもかかわらず、 クライアントが「signature_algorithms」拡張を送信していない場合、 サーバーは「missing_extension」アラートによってハンドシェイクを 中止しなければならない第9.2節を参照)。

「signature_algorithms_cert」拡張は、 証明書とTLS自体で異なるアルゴリズム群をサポートする実装が、 その能力を明確に通知できるようにするために追加された。 TLS 1.2実装もこの拡張を 処理することが望ましい。 両方の場合で同じポリシーを持つ実装は、 「signature_algorithms_cert」拡張を 省略してもよい

これらの拡張の「extension_data」フィールドには、 SignatureSchemeList値が含まれる。

   enum {
       /* RSASSA-PKCS1-v1_5アルゴリズム */
       rsa_pkcs1_sha256(0x0401),
       rsa_pkcs1_sha384(0x0501),
       rsa_pkcs1_sha512(0x0601),

       /* ECDSAアルゴリズム */
       ecdsa_secp256r1_sha256(0x0403),
       ecdsa_secp384r1_sha384(0x0503),
       ecdsa_secp521r1_sha512(0x0603),

       /* 公開鍵OIDがrsaEncryptionであるRSASSA-PSSアルゴリズム */
       rsa_pss_rsae_sha256(0x0804),
       rsa_pss_rsae_sha384(0x0805),
       rsa_pss_rsae_sha512(0x0806),

       /* EdDSAアルゴリズム */
       ed25519(0x0807),
       ed448(0x0808),

       /* 公開鍵OIDがRSASSA-PSSであるRSASSA-PSSアルゴリズム */
       rsa_pss_pss_sha256(0x0809),
       rsa_pss_pss_sha384(0x080a),
       rsa_pss_pss_sha512(0x080b),

       /* レガシーアルゴリズム */
       rsa_pkcs1_sha1(0x0201),
       ecdsa_sha1(0x0203),

       /* 予約済みコードポイント */
       private_use(0xFE00..0xFFFF),
       (0xFFFF)
   } SignatureScheme;

   struct {
       SignatureScheme supported_signature_algorithms<2..2^16-2>;
   } SignatureSchemeList;

注: この列挙型が「SignatureScheme」と名付けられているのは、 TLS 1.2に、この型が置き換える 「SignatureAlgorithm」型がすでに存在するためである。 本文では一貫して「署名アルゴリズム」という用語を使用する。

各SignatureScheme値は、 クライアントが検証する用意のある単一の署名アルゴリズムを列挙する。 値は選好の降順で示される。署名アルゴリズムは、 ダイジェストではなく任意長のメッセージを入力として受け取ることに注意されたい。 従来ダイジェストに対して動作するアルゴリズムは、 TLSではまず指定されたハッシュアルゴリズムで入力をハッシュし、 その後、通常どおり処理するよう定義すべきである。 上記のコードポイント群には、次の意味がある。

RSASSA-PKCS1-v1_5アルゴリズム:

[RFC8017]で定義されるRSASSA-PKCS1-v1_5と、 [SHS]で定義される対応するハッシュアルゴリズムを 使用する署名アルゴリズムを示す。 これらの値は、証明書内に現れる署名だけを指し (第4.5.1.2節を参照)、 署名付きTLSハンドシェイクメッセージで使用するためには定義されていない。 ただし、TLS 1.2との後方互換性のために、 「signature_algorithms」および 「signature_algorithms_cert」に 現れてもよい

ECDSAアルゴリズム:

ECDSA [DSS]、 NIST SP 800-186 [ECDP]で定義される対応する曲線、および [SHS]で定義される対応するハッシュアルゴリズムを 使用する署名アルゴリズムを示す。 署名は、[RFC4492]で定義される、 DER符号化された[X690] ECDSA-Sig-Value構造体として表される。

RSASSA-PSS RSAEアルゴリズム:

[RFC8017]で定義される MGF1のマスク生成関数を使用するRSASSA-PSS署名アルゴリズムを示す。 MGF1で使用されるダイジェストと署名対象のダイジェストは、 いずれも[SHS]で定義される対応するハッシュアルゴリズムである。 Saltの長さは、ダイジェストアルゴリズムの出力の長さと等しく なければならない。 公開鍵がX.509証明書で搬送される場合、 rsaEncryption OID [RFC3279]使用しなければならない

EdDSAアルゴリズム:

[RFC8032]またはその後継仕様で 定義されるEdDSAを使用する署名アルゴリズムを示す。 これらは「PureEdDSA」アルゴリズムに対応し、 「prehash」変種には対応しないことに注意されたい。

RSASSA-PSS PSSアルゴリズム:

[RFC8017]で定義される MGF1のマスク生成関数を使用するRSASSA-PSS署名アルゴリズムを示す。 MGF1で使用されるダイジェストと署名対象のダイジェストは、 いずれも[SHS]で定義される対応するハッシュアルゴリズムである。 Saltの長さはダイジェストアルゴリズムの長さと等しく なければならない。 公開鍵がX.509証明書で搬送される場合、 RSASSA-PSS OID [RFC5756]使用しなければならない。 証明書署名で使用する場合、 アルゴリズムパラメーターはDER符号化 しなければならない。 対応する公開鍵のパラメーターが存在する場合、 署名内のパラメーターは公開鍵内のものと同一で なければならない

レガシーアルゴリズム:

既知の弱点を持つアルゴリズムを使用するため 非推奨となっているアルゴリズムを示す。 具体的には、このコンテキストで (1)RSASSA-PKCS1-v1_5を使用するRSA、または (2)ECDSAとともに使用されるSHA-1である。 これらの値は、証明書内に現れる署名だけを指し (第4.5.1.2節を参照)、 署名付きTLSハンドシェイクメッセージで使用するためには定義されていない。 ただし、TLS 1.2との後方互換性のために、 「signature_algorithms」および 「signature_algorithms_cert」に 現れてもよい。 エンドポイントはこれらのアルゴリズムを ネゴシエートしないことが望ましいが、 後方互換性のために限りネゴシエートすることが許可される。 これらの値を提示するクライアントは、 それらを最低の優先順位 (SignatureSchemeList内で他のすべてのアルゴリズムの後)に 列挙しなければならない。 TLS 1.3サーバーは、SHA-1を使用せずに有効な証明書チェーンを 生成できない場合を除き、SHA-1署名証明書を 提示してはならない第4.5.1.2節を参照)。

自己署名証明書またはトラストアンカーである証明書の署名は、 証明パスの起点となるため検証されない ([RFC5280]の第 3.2節を参照)。 証明パスを開始する証明書は、 「signature_algorithms」および 「signature_algorithms_cert」拡張でサポートされると広告されていない 署名アルゴリズムを使用してもよい

TLS 1.2では、この拡張が異なる形で定義されていることに注意されたい。 TLS 1.2をネゴシエートする用意のあるTLS 1.3実装は、 そのバージョンをネゴシエートする際、 [RFC5246]の要件に従って 動作しなければならない。 特に、次のとおりである。

  • TLS 1.2 ClientHelloは、この拡張を 省略してもよい

  • TLS 1.2では、この拡張にハッシュ/署名の ペアが含まれていた。このペアは2オクテットで符号化されるため、 SignatureScheme値はTLS 1.2の符号化と整合するように割り当てられている。 一部のレガシーペアは未割り当てのままである。 これらのアルゴリズムはTLS 1.3で非推奨となった。 どの実装もこれらを提示またはネゴシエート してはならない。 特に、MD5 [SLOTH]、SHA-224、および DSAを使用してはならない

  • ECDSA署名方式は、TLS 1.2のECDSA ハッシュ/署名のペアと整合する。 ただし、以前のセマンティクスでは署名曲線に制約がなかった。 TLS 1.2がネゴシエートされた場合、実装は 「supported_groups」拡張で広告した任意の曲線を使用する署名を 受け入れる用意がなければならない

  • RSASSA-PSS (TLS 1.3では必須)へのサポートを広告する実装は、 TLS 1.2がネゴシエートされた場合でも、その方式を使用する署名を 受け入れる用意がなければならない。 TLS 1.2では、RSASSA-PSSはRSA暗号スイートとともに使用される。

4.3.4. 認証局

「certificate_authorities」拡張は、 エンドポイントがサポートする認証局(CA)を示すために使用され、 受信側エンドポイントは証明書の選択を導くために それらを使用することが望ましい

「certificate_authorities」拡張の本体は、 CertificateAuthoritiesExtension構造体からなる。

   opaque DistinguishedName<1..2^16-1>;

   struct {
       DistinguishedName authorities<3..2^16-1>;
   } CertificateAuthoritiesExtension;
authorities:

受け入れ可能な認証局の識別名 [X501]の一覧。 DER符号化された[X690]形式で表される。 これらの識別名は、トラストアンカーまたは下位CAに求める 識別名を指定するため、このメッセージは、 既知のトラストアンカーと求める認可空間の両方を 記述するために使用できる。

クライアントはClientHelloメッセージで 「certificate_authorities」拡張を 送信してもよい。 サーバーはCertificateRequestメッセージでこれを 送信してもよい

同様の目的を持つが、より複雑な 「trusted_ca_keys」拡張 [RFC6066]は、TLS 1.3では使用されない (ただし、以前のバージョンのTLSを提示するクライアントからの ClientHelloメッセージに現れる場合がある)。

4.3.5. OIDフィルター

「oid_filters」拡張により、サーバーは、 クライアントの証明書が一致することを望むOID/値の ペアの一覧を提供できる。 この拡張をサーバーが提供する場合、 CertificateRequestメッセージでだけ 送信しなければならない

   struct {
       opaque certificate_extension_oid<1..2^8-1>;
       opaque certificate_extension_values<0..2^16-1>;
   } OIDFilter;

   struct {
       OIDFilter filters<0..2^16-1>;
   } OIDFilterExtension;
filters:

許可される値とともにDER符号化された [X690]形式で表される、 証明書拡張OID [RFC5280]の一覧。 一部の証明書拡張OIDは複数の値を許可する (例えば、拡張鍵用途)。 サーバーが空でないfilters一覧を含めた場合、 応答に含まれるクライアント証明書は、 クライアントが認識する指定されたすべての拡張OIDを 含まなければならない。 クライアントが認識する各拡張OIDについて、 指定されたすべての値がクライアント証明書に 存在しなければならない (ただし、証明書はその他の値も 持ってもよい)。 ただし、クライアントは認識できない証明書拡張OIDを 無視して読み飛ばさなければならない。 クライアントが必要な証明書拡張OIDの一部を無視し、 要求を満たさない証明書を提供した場合、 サーバーは裁量により、クライアント認証なしで接続を 続行するか、「unsupported_certificate」アラートによって ハンドシェイクを中止してもよい。 指定されたOIDはfilters一覧に複数回 現れてはならない

PKIX RFCは、さまざまな証明書拡張OIDと、 対応する値の型を定義している。 型によっては、一致する証明書拡張値が 必ずしもビット単位で等しいとは限らない。 TLS実装は、証明書拡張OIDを使用した証明書選択を実行するために、 PKIライブラリに依存することが想定される。

本文書は、[RFC5280]で定義される2つの標準証明書拡張について、 一致規則を定義する。

  • 証明書内のKey Usage拡張は、 要求で表明されたすべての鍵用途ビットが、 証明書のKey Usage拡張でも表明されている場合、 要求と一致する。

  • 証明書内のExtended Key Usage拡張は、 要求に存在するすべての鍵目的OIDが、 証明書のExtended Key Usage拡張にも見つかる場合、 要求と一致する。特別なanyExtendedKeyUsage OIDは、 要求で使用してはならない

別の仕様で、その他の証明書 拡張に対する一致規則が定義される場合がある。

4.3.6. ハンドシェイク後の 証明書ベースのクライアント認証

「post_handshake_auth」拡張は、 クライアントがハンドシェイク後認証 (第4.7.2節)を実行する用意があることを示すために 使用される。この拡張を提示しないクライアントに、 サーバーはハンドシェイク後のCertificateRequestを 送信してはならない。 サーバーはこの拡張を送信してはならない

   struct {} PostHandshakeAuth;

「post_handshake_auth」拡張の「extension_data」フィールドは、 長さ0である。

4.3.7. サポートされるグループ

クライアントによって送信される場合、 「supported_groups」拡張は、 クライアントが鍵交換でサポートする名前付きグループを、 最も優先されるものから最も優先されないものの順に示す。

注: TLS 1.3より前のバージョンのTLSでは、 この拡張は「elliptic_curves」と呼ばれ、 楕円曲線グループだけを含んでいた。 [RFC8422]および [RFC7919]を参照。 この拡張はECDSA曲線のネゴシエーションにも使用されていた。 署名アルゴリズムは現在、独立してネゴシエートされる (第4.3.3節を参照)。

この拡張の「extension_data」フィールドには、 「NamedGroupList」値が含まれる。

   enum {

       /* 楕円曲線グループ(ECDHE) */
       secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019),
       x25519(0x001D), x448(0x001E),

       /* 有限体グループ(DHE) */
       ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102),
       ffdhe6144(0x0103), ffdhe8192(0x0104),

       /* 予約済みコードポイント */
       ffdhe_private_use(0x01FC..0x01FF),
       ecdhe_private_use(0xFE00..0xFEFF),
       (0xFFFF)
   } NamedGroup;

   struct {
       NamedGroup named_group_list<2..2^16-1>;
   } NamedGroupList;
楕円曲線グループ(ECDHE):

NIST SP 800-186 [ECDP]または[RFC7748]のいずれかで定義される、 対応する名前付き曲線のサポートを示す。 値0xFE00から0xFEFFは、Private Use [RFC8126]用に予約される。

有限体グループ(DHE):

[RFC7919]で定義される、 対応する有限体グループのサポートを示す。 値0x01FCから0x01FFは、Private Use用に予約される。

「named_group_list」内の項目は、送信者の 選好順(最も優先される選択肢が先頭)に並べられる。 「named_group_list」は重複する項目を 含んではならない。 受信者は、重複する項目を検出した場合、 致命的な「illegal_parameter」アラートによって接続を 中止してもよい

TLS 1.3以降、サーバーはクライアントに 「supported_groups」拡張を送信することが許可される。 クライアントは、ハンドシェイクが正常に完了する前に 「supported_groups」で見つかった情報に基づいて 動作してはならないが、 正常に完了したハンドシェイクから得られた情報を使用して、 後続の接続における「key_share」拡張で使用するグループを 変更してもよい。 サーバーが「key_share」拡張内のグループより優先するグループを持つが、 それでもClientHelloを受け入れる用意がある場合、 クライアントが認識するサーバーの選好を更新するために 「supported_groups」を送信 することが望ましい。 この拡張は、クライアントが現在サポートしているかどうかにかかわらず、 サーバーがサポートするすべてのグループを 含むことが望ましい

4.3.8. 鍵共有

「key_share」拡張には、エンドポイントの暗号 パラメーターが含まれる。

クライアントは、追加のラウンドトリップを代償として、 サーバーにグループの選択を要求するため、 空のclient_shares一覧を 送信してもよい第4.2.4節を参照)。

   struct {
       NamedGroup group;
       opaque key_exchange<1..2^16-1>;
   } KeyShareEntry;
group:

交換される鍵の名前付きグループ。

key_exchange:

鍵交換情報。このフィールドの内容は、 指定されたグループおよびそれに対応する定義によって決まる。 有限体Diffie-Hellman [DH76]パラメーターについては、 第4.3.8.1節で説明する。 楕円曲線Diffie-Hellmanパラメーターについては、 第 4.3.8.2節で説明する。

ClientHelloメッセージでは、この拡張の 「extension_data」フィールドに 「KeyShareClientHello」値が含まれる。

   struct {
       KeyShareEntry client_shares<0..2^16-1>;
   } KeyShareClientHello;
client_shares:

クライアントの選好順に降順で並べられた、 提示するKeyShareEntry値の一覧。

クライアントがHelloRetryRequestを要求している場合、 この一覧は空であってもよい。 各KeyShareEntry値は、 「supported_groups」拡張で提示されたグループに対応し、 同じ順序で現れなければならない。 ただし、値は「supported_groups」拡張の 非連続な部分集合であってもよく、 最も優先されるグループを省略してもよい。 このような状況は、最も優先されるグループが新しく、 十分な場所でサポートされる可能性が低いため、 それらの鍵共有を事前生成することが効率的でない場合に生じる可能性がある。

このため、グループAの共有値を省略し、 グループBの共有値を含めたからといって、 クライアントがAよりBを優先していることを意味しない。 KeyShareEntryに基づいてグループを選択すると、 クライアントとサーバーが相互にサポートするグループより 優先度の低いグループが使用される可能性があるが、 HelloRetryRequestのラウンドトリップを省略できる。 クライアントのグループ選好を尊重したいサーバーは、 まず「supported_groups」に基づいてグループを選択し、 次にKeyshareClientHelloの内容に応じてServerHelloまたは HelloRetryRequestを送信 することが望ましい

クライアントは、提示するサポート対象グループの数と同じだけの KeyShareEntry値を提示でき、 各値は単一の鍵交換パラメーター群を表す。 例えば、クライアントは複数の楕円曲線または複数の FFDHEグループについて共有値を提示できる。 各KeyShareEntryのkey_exchange値は、 独立して生成しなければならない。 クライアントは、同じグループに対して複数のKeyShareEntry値を 提示してはならない。 クライアントは、「supported_groups」拡張に列挙されていない グループに対してKeyShareEntry値を 提示してはならない。 サーバーはこれらの規則への違反を確認し、 違反がある場合、「illegal_parameter」アラートによって ハンドシェイクを中止してもよい

クライアントおよびサーバーは、複数の接続で 鍵共有を再利用してはならない[RFC8446]では再利用が許可されていたため、 相互運用性の問題を防ぐため、受信側実装はピアによる再利用を 許可しなければならない

HelloRetryRequestメッセージでは、この拡張の 「extension_data」フィールドに KeyShareHelloRetryRequest値が含まれる。

   struct {
       NamedGroup selected_group;
   } KeyShareHelloRetryRequest;
selected_group:

サーバーがネゴシエートする予定であり、 再試行される ClientHello/KeyShareを要求している、相互にサポートされるグループ。

HelloRetryRequestでこの拡張を受信した場合、クライアントは 次のことを検証しなければならない。 (1)selected_groupフィールドが、元のClientHello内の 「supported_groups」拡張で提供されたグループに対応すること、および(2) selected_groupフィールドが、元のClientHello内の 「key_share」拡張で提供されたグループに対応しないこと。これらの 確認のいずれかに失敗した場合、クライアントはハンドシェイクを中止しなければならない。 その際、 「illegal_parameter」アラートを使用する。それ以外の場合、新しいClientHelloを送信するとき、 クライアントは、元の「key_share」拡張を 置き換えなければならない。 置き換え後の拡張には、 HelloRetryRequestを引き起こしたselected_groupフィールドで示された グループの新しいKeyShareEntryだけを含める。

ServerHelloメッセージでは、この拡張の「extension_data」フィールドに KeyShareServerHello値が含まれる。

   struct {
       KeyShareEntry server_share;
   } KeyShareServerHello;
server_share:

クライアントの共有値の1つと同じグループに属する 単一の KeyShareEntry値。

非対称鍵確立を使用する場合、サーバーはServerHelloで正確に1つの KeyShareEntryを提示する。この値は、ネゴシエートされた鍵交換用に サーバーが選択した、 クライアントが提示したKeyShareEntry値と同じグループに 属していなければならない。 サーバーは、クライアントの「supported_groups」拡張で 示されていないグループに対するKeyShareEntryを 送信してはならず、「psk_ke」 PskKeyExchangeModeを使用する場合もKeyShareEntryを送信してはならない。 非対称鍵確立を使用し、「key_share」拡張を含む HelloRetryRequestをクライアントが受信していた場合、クライアントは、 ServerHello内で選択されたNamedGroupがHelloRetryRequest内のものと同じであることを 検証しなければならない。 この確認に失敗した場合、クライアントは 「illegal_parameter」 アラートによってハンドシェイクを中止しなければならない

4.3.8.1. Diffie-Hellmanパラメーター

クライアントおよび サーバーのDiffie-Hellman [DH76]パラメーターは、 KeyShare構造体内のKeyShareEntryのopaque key_exchangeフィールドに 符号化される。opaque値には、 指定されたグループのDiffie-Hellman公開値 (Y = gX mod p)が含まれる (グループの定義については[RFC7919]を 参照)。 この値はビッグエンディアン整数として符号化され、 バイト単位のpのサイズになるまで左側を0で パディングされる。

注: 指定されたDiffie-Hellmanグループでは、 パディングによってすべての公開鍵が 同じ長さになる。

ピアは、1 < Y < p-1であることを保証することにより、相互の公開鍵Yを 検証しなければならない。この確認により、リモートピアが適切に動作し、 ローカルシステムを小さな部分群へ強制していないことが保証される。

4.3.8.2. ECDHE パラメーター

クライアントおよびサーバーのECDHEパラメーターは、 KeyShare構造体内の KeyShareEntryのopaque key_exchangeフィールドに符号化される。

secp256r1、secp384r1、およびsecp521r1では、内容は 次の構造体をシリアライズした 値である。

   struct {
       uint8 legacy_form = 4;
       opaque X[coordinate_length];
       opaque Y[coordinate_length];
   } UncompressedPointRepresentation;

XおよびYは、それぞれ x値およびy値をネットワークバイト順で表したバイナリ表現である。 内部の長さマーカーは存在しないため、 各数値表現は曲線パラメーターから示される数の オクテットを占有する。P-256では、XおよびYがそれぞれ 32オクテットを使用し、必要に応じて左側を0でパディングする。 P-384では、それぞれ48オクテットを使用する。P-521では、それぞれ66オクテットを使用する。

曲線secp256r1、secp384r1、およびsecp521r1では、 ピアは、点が楕円曲線上の有効な点であることを 保証することにより、相互の公開値Qを検証しなければならない。 適切な検証手順は、[ECDP]の付録D.1、 または[KEYAGREEMENT]の第5.6.2.3節で定義される。 この処理は3つの 手順からなる。(1)Qが無限遠点(O)ではないことを検証する、(2) Q = (x, y)について、整数xおよびyの両方が正しい範囲内にあることを検証する、(3) (x, y)が楕円曲線 方程式の正しい解であることを保証する。これらの曲線では、実装者は 正しい部分群への所属を検証する必要はない。

X25519およびX448では、公開値の内容は、 [RFC7748]の第6節で説明されるK_A またはK_B値である。 X25519では32バイト、X448では56バイトである。

注: TLS 1.3より前のバージョンでは、点形式の ネゴシエーションが許可されていた。 TLS 1.3では、この機能を削除し、各曲線に対して単一の点形式を 使用する。

4.3.9. 事前共有鍵 交換モード

PSKを使用するため、クライアントは 「psk_key_exchange_modes」拡張も 送信しなければならない。この拡張のセマンティクスは、 クライアントがこれらのモードとともにだけPSKの使用をサポートするというものであり、 このClientHelloで提示されるPSKと、サーバーが NewSessionTicketによって提供する可能性があるPSKの両方の使用を制限する。

クライアントが 「pre_shared_key」拡張を提示する場合、 「psk_key_exchange_modes」拡張を提供しなければならない。 クライアントが「psk_key_exchange_modes」拡張なしで「pre_shared_key」を提示した場合、 サーバーはハンドシェイクを中止しなければならない。 サーバーは、クライアントが列挙していない鍵交換モードを 選択してはならない。 この拡張は、PSK再開で使用するモードも制限する。 サーバーは、広告されたモードと互換性のないチケットを含むNewSessionTicketを 送信しないことが望ましい。 ただし、サーバーがそのようにした場合の影響は、 クライアントによる再開の試行が失敗するだけである。

サーバーは 「psk_key_exchange_modes」拡張を送信してはならない

   enum { psk_ke(0), psk_dhe_ke(1), (255) } PskKeyExchangeMode;

   struct {
       PskKeyExchangeMode ke_modes<1..255>;
   } PskKeyExchangeModes;
psk_ke:

PSKだけによる鍵確立。このモードでは、サーバーは 「key_share」値を 提供してはならない

psk_dhe_ke:

非対称鍵確立を伴うPSK(「dhe」というラベルは、 非DHE鍵確立アルゴリズムをサポートしていなかった TLS 1.3の初期版に由来する歴史的なものである)。このモードでは、 クライアントおよびサーバーは「key_share」値を 提供しなければならない。 詳細は第4.3.8節を参照。

将来割り当てられる値は、送信される プロトコルメッセージによって、 サーバーが選択したモードを明確に識別できることを保証しなければならない。 現時点では、これはServerHello内の「key_share」の存在によって示される。

4.3.10. 早期データ 指示

PSKを使用し、そのPSKで早期データが許可される場合 (例えば、付録 B.3.4を参照)、クライアントは最初のメッセージフライトでApplication Dataを 送信できる。クライアントがこれを行うことを選択した場合、 「pre_shared_key」および「early_data」の両方の拡張を提供しなければならない

この拡張の「extension_data」フィールドには、 「EarlyDataIndication」値が含まれる。

   struct {} Empty;

   struct {
       select (Handshake.msg_type) {
           case new_session_ticket:   uint32 max_early_data_size;
           case client_hello:         Empty;
           case encrypted_extensions: Empty;
       };
   } EarlyDataIndication;

max_early_data_sizeフィールドの使用に関する詳細については、 第 4.7.1節を参照されたい。

0-RTTデータのパラメーター(バージョン、対称暗号スイート、 Application-Layer Protocol Negotiation(ALPN)[RFC7301]プロトコル など)は、使用するPSKに関連付けられたものである。 外部でプロビジョニングされたPSKでは、関連付けられた値は 鍵とともにプロビジョニングされた値である。NewSessionTicket メッセージによって確立されたPSKでは、関連付けられた値は、 PSKを確立した接続でネゴシエートされた値である。早期データの暗号化に使用されるPSKは、 クライアントの「pre_shared_key」拡張に列挙された最初のPSKで なければならない

NewSessionTicketによってプロビジョニングされたPSKでは、サーバーは、 選択したPSK識別情報のチケットの経過時間 (PskIdentity.obfuscated_ticket_ageから ticket_age_addを232を法として減算して計算)が、 チケットの発行から経過した時間の小さな許容範囲内にあることを 検証しなければならない第8節を参照)。そうでない場合、 サーバーはハンドシェイクを続行するが0-RTTを拒否 することが望ましく、 このClientHelloが新しいことを前提とするその他の処理を 行わないことが望ましい

最初のフライトで送信される0-RTTメッセージは、 その他のフライトで送信される同じ種類のメッセージと同じ(暗号化された) コンテンツタイプ(handshakeおよび application_data)を持つが、 異なる鍵によって保護される。サーバーのFinishedメッセージを受信した後、 サーバーが早期データを受け入れた場合、鍵の変更を示す EndOfEarlyDataメッセージが送信される。このメッセージは、 0-RTTトラフィック鍵によって暗号化される。

「early_data」拡張を受信したサーバーは、 次の3つの方法のいずれかで 動作しなければならない

  • 拡張を無視し、通常の1-RTT 応答を返す。サーバーは、 ハンドシェイクトラフィック鍵を使用して受信レコードの 保護解除を試み、保護解除に失敗したレコードを (設定されたmax_early_data_sizeまで) 破棄することで早期データを読み飛ばす。 レコードの保護解除に成功すると、 それをクライアントの2番目のフライトの開始として扱い、 通常の1-RTTハンドシェイクと同様に処理を続行する。

  • HelloRetryRequestで 応答することにより、クライアントに別のClientHelloを送信するよう要求する。 クライアントは、後続のClientHelloに 「early_data」拡張を含めてはならない。 サーバーは、設定されたmax_early_data_sizeまで、 外部コンテンツタイプが「application_data」である (暗号化されていることを示す)すべてのレコードを読み飛ばすことで、 早期データを無視する。

  • EncryptedExtensionsで独自の「early_data」拡張を 返し、 早期データを処理する予定であることを 示す。サーバーが 早期データメッセージの一部だけを受け入れることはできない。 サーバーは早期データを受け入れるメッセージを送信するが、実際の早期 データ自体は、サーバーがこのメッセージを生成する時点で、 すでに転送中である可能性がある。

早期データを受け入れるには、サーバーは、 クライアントの「pre_shared_key」拡張で提示された最初の 鍵を選択していなければならない。さらに、 次の値が 選択されたPSKに関連付けられた値と同じであることを 検証しなければならない

  • 選択されたTLSバージョン番号

  • 選択された暗号スイート

  • 選択されたALPN [RFC7301]プロトコル(存在する場合)

これらの要件は、対象のPSKを使用して 1-RTT ハンドシェイクを実行するために必要な要件を包含する。

将来の拡張は、0-RTTとの 相互作用を定義しなければならない

これらの確認のいずれかに失敗した場合、サーバーは拡張で 応答してはならず、 上記の最初の2つの機構のいずれかを使用して、 最初のフライトのすべてのデータを破棄しなければならない (したがって、1-RTTまたは2-RTTにフォールバックする)。クライアントが 0-RTTハンドシェイクを試みたがサーバーが拒否した場合、サーバーは通常、 0-RTTレコード保護鍵を持たないため、 試行復号(1-RTTハンドシェイク鍵を使用するか、 HelloRetryRequestの場合は平文のClientHelloを探す)によって 最初の0-RTTでないメッセージを見つける必要がある。

サーバーが「early_data」拡張を受け入れることを選択した場合、 早期データレコードを処理する際、すべてのレコードに対して規定されているものと同じ エラー処理要件に従わなければならない。 具体的には、受け入れた「early_data」拡張に続く 0-RTTレコードの復号に失敗した場合、サーバーは 「bad_record_mac」アラートによって接続を 終了しなければならない。 詳細は第5.2節を参照。

サーバーが「early_data」拡張を拒否した場合、クライアント アプリケーションは、ハンドシェイクの完了後、 早期データで以前に送信したApplication Dataを再送信することを 選択してもよい。早期データの 自動再送信は、接続の状態について誤った前提を生じさせる可能性がある。 例えば、ネゴシエートされた接続が、 早期データで使用されたものとは異なるALPNプロトコルを選択した場合、 アプリケーションは異なるメッセージを構築する必要がある場合がある。同様に、 早期データが接続状態について何らかの前提を置いている場合、 ハンドシェイクの完了後に誤って送信される可能性がある。

TLS実装は、 早期データを自動的に再送信しないことが望ましい。 再送信が適切な時期を判断するには、アプリケーションの方が適している。 ネゴシエートされた接続が同じALPN プロトコルを選択しない限り、TLS実装は早期データを自動的に 再送信してはならない

4.3.11. 事前共有鍵 拡張

「pre_shared_key」拡張は、PSK鍵確立と関連付けて、 指定されたハンドシェイクで使用する 事前共有鍵の識別情報をネゴシエートするために使用される。

この拡張の「extension_data」フィールドには、 「PreSharedKeyExtension」値が含まれる。

   struct {
       opaque identity<1..2^16-1>;
       uint32 obfuscated_ticket_age;
   } PskIdentity;

   opaque PskBinderEntry<32..255>;

   struct {
       PskIdentity identities<7..2^16-1>;
       PskBinderEntry binders<33..2^16-1>;
   } OfferedPsks;

   struct {
       select (Handshake.msg_type) {
           case client_hello: OfferedPsks;
           case server_hello: uint16 selected_identity;
       };
   } PreSharedKeyExtension;
identity:

鍵のラベル。例えば、チケット (付録 B.3.4で定義)または、外部で確立された事前共有鍵の ラベル。

obfuscated_ticket_age:

鍵の経過時間を難読化したもの。 第4.3.11.1節では、 NewSessionTicketメッセージによって確立された識別情報について、 この値を構成する方法を説明する。 外部で確立された識別情報では、0のobfuscated_ticket_ageを 使用することが望ましく、サーバーは その値を無視しなければならない

identities:

クライアントが サーバーとネゴシエートする用意のある識別情報の一覧。「early_data」 拡張(第4.3.10節を参照)とともに送信される場合、最初の識別情報が 0-RTTデータに使用される。

binders:

identities一覧の各値に対して1つずつ、 同じ 順序で、以下で説明するように計算された一連のHMAC値。

selected_identity:

クライアントの 「OfferedPsks.identities」一覧内のidentitiesへの 0始まりのインデックスとして表される、サーバーが選択した識別情報。

各PSKは単一のHashアルゴリズムに関連付けられる。 チケット機構 (第 4.7.1節)によって確立されたPSKでは、チケットが確立された接続における KDF Hashアルゴリズムである。 外部で確立されたPSKでは、Hashアルゴリズムは、 PSKの確立時に設定しなければならず、 そのようなアルゴリズムが定義されていない場合はSHA-256を既定値とする。 サーバーは、互換性のある PSK(存在する場合)および暗号スイートを選択することを 保証しなければならない

TLS 1.3より前のTLSバージョンでは、Server Name Indication(SNI) 値は セッションに関連付けられることを意図していた ([RFC6066]の第3節)。 サーバーは、セッションに関連付けられたSNI値が、 再開ハンドシェイクで指定された値と一致することを保証する必要があった。しかし実際には、 提供された2つのSNI値のどちらを使用するかについて 実装間で一貫性がなく、一貫性要件は事実上 クライアントによって強制されることになった。TLS 1.3では、SNI値は 再開ハンドシェイクで常に明示的に指定され、サーバーがSNI値を チケットに関連付ける必要は ない。ただし、クライアントは 第 4.7.1節の要件を満たすため、SNIをPSKとともに保存 することが望ましい

実装者への注記: セッション再開がPSKの主な使用例である場合、 PSK/暗号スイートの一致要件を実装する 最も直接的な方法は、まず暗号スイートを ネゴシエートし、その後、互換性のないPSKを除外することである。未知のPSK (例えば、PSKデータベースにないもの、または 未知の鍵で暗号化されたもの)は単に 無視することが望ましい。受け入れ可能なPSKが 見つからない場合、可能であればサーバーは非PSKハンドシェイクを 実行することが望ましい。 後方互換性が重要な場合、クライアントが提供し、外部で 確立されたPSKは暗号スイートの選択に影響を与える ことが望ましい

PSK鍵確立を受け入れる前に、サーバーは 対応するバインダー値 (以下の第 4.3.11.2節を参照)を検証しなければならない。 この値が存在しないか、検証に失敗した場合、サーバーは ハンドシェイクを中止しなければならない。 サーバーは複数のバインダーの検証を試み ないことが望ましく、代わりに、 単一のPSKを選択し、そのPSKに対応するバインダーだけを 検証することが望ましい。 この要件のセキュリティ上の根拠については、 第8.2節および付録F.6を参照されたい。 PSK鍵確立を受け入れるため、 サーバーは選択された 識別情報を示す「pre_shared_key」拡張を送信する。

クライアントは、サーバーの selected_identityがクライアントによって提供された 範囲内にあること、サーバーがPSKに関連付けられたHashを示す暗号スイートを 選択したこと、および ClientHelloの「psk_key_exchange_modes」拡張によって必要とされる場合、 サーバーの「key_share」拡張が存在することを 検証しなければならない。これらの値に 整合性がない場合、クライアントは 「illegal_parameter」アラートによってハンドシェイクを 中止しなければならない

サーバーが「early_data」拡張を提供する場合、クライアントは サーバーのselected_identityが0であることを 検証しなければならない。 その他の値が返された場合、クライアントは 「illegal_parameter」アラートによってハンドシェイクを 中止しなければならない

「pre_shared_key」拡張は、 ClientHello内の 最後の拡張でなければならない (これにより、以下で説明するように実装が容易になる)。サーバーは、 それが最後の拡張であることを確認しなければならず、 そうでない場合、 「illegal_parameter」アラートによってハンドシェイクを失敗させなければならない。

4.3.11.1. チケットの経過時間

クライアントから見たチケットの経過時間は、 NewSessionTicketメッセージを受信してからの 時間である。クライアントは、 チケットとともに提供された「ticket_lifetime」値より 経過時間が大きいチケットを 使用しようとしてはならない。 各PskIdentityの「obfuscated_ticket_age」フィールドには、 ミリ秒単位の経過時間に、チケットとともに含まれていた 「ticket_age_add」 値(第4.7.1節を参照)を加え、 232を法とすることで構成される、チケットの経過時間を難読化した値が含まれる。 チケットまたは鍵共有が再利用されない限り、この加算により、 受動的な観測者が接続を関連付けることを防止する。 NewSessionTicketメッセージ内の「ticket_lifetime」フィールドは 秒単位であるが、「obfuscated_ticket_age」は ミリ秒単位であることに注意されたい。チケットの有効期間は 1週間に制限されているため、32ビットで、 ミリ秒単位であっても現実的なすべての 経過時間を表現するのに十分である。

4.3.11.2. PSKバインダー

PSKバインダー値は、PSKと 現在のハンドシェイクとの間、およびPSKが 生成されたハンドシェイク (NewSessionTicketメッセージによる場合)と現在のハンドシェイクとの間に結び付きを形成する。 binders一覧の各項目は、 PreSharedKeyExtension.identitiesフィールドまでを含む 部分的なClientHelloを含むトランスクリプトハッシュ (第4.1節を参照)に対するHMACとして計算される。すなわち、 ClientHello全体を含むが、binders一覧 自体は含まない。メッセージの長さフィールド (全体の長さ、extensionsブロックの長さ、および 「pre_shared_key」拡張の長さを含む)はすべて、 正しい長さのバインダーが 存在するものとして設定される。

PskBinderEntryは Finishedメッセージ (第4.5.3節)と同じ方法で計算されるが、 BaseKeyには、提示されている対応するPSKから 鍵スケジュールによって導出されたbinder_keyを使用する (第 7.1節を参照)。

ハンドシェイクにHelloRetryRequestが含まれる場合、 最初のClientHello およびHelloRetryRequestは、 新しいClientHelloとともにトランスクリプトに含まれる。例えば、 クライアントがClientHello1を送信する場合、そのバインダーは次のものに対して計算される。

   Transcript-Hash(Truncate(ClientHello1))

ここで、Truncate()は ClientHelloからbinders一覧を削除する。 クライアントはサーバーが選択する暗号スイートを認識していないため、 このハッシュはPSKに関連付けられたハッシュを使用して 計算されることに注意されたい。

サーバーがHelloRetryRequestで応答し、 その後クライアントが ClientHello2を送信する場合、そのバインダーは次のものに対して計算される。

   Transcript-Hash(ClientHello1,
                   HelloRetryRequest,
                   Truncate(ClientHello2))

完全なClientHello1/ClientHello2は、 その他のすべてのハンドシェイクハッシュ計算に含まれる。 最初のフライトではTruncate(ClientHello1)が直接ハッシュされるが、 2番目のフライトでは、ClientHello1がハッシュされ、その後 「message_hash」メッセージとして再挿入されることに注意されたい。詳細は、第4.1節を参照。 「message_hash」はネゴシエートされた関数でハッシュされ、 その関数はPSKに関連付けられたハッシュと一致する場合もあれば、一致しない場合もある。 これは、ハンドシェイクの残りでトランスクリプトが計算される方法と 整合している。

4.3.11.3. 処理 順序

クライアントは、サーバーのFinishedを受信するまで 0-RTTデータを「ストリーム」することが許可され、 その後にだけEndOfEarlyData メッセージを送信し、続いてハンドシェイクの残りを送信する。 デッドロックを回避するため、「early_data」を受け入れる場合、 サーバーはクライアントのClientHelloを処理しなければならず、 その後直ちに 自身のメッセージフライトを送信しなければならない。クライアントの EndOfEarlyDataメッセージを待ってからServerHelloを送信してはならない。

4.4. サーバーパラメーター

サーバーからの次の2つのメッセージ、EncryptedExtensionsおよび CertificateRequestには、ハンドシェイクの残りを 決定するサーバーからの情報が含まれる。これらのメッセージは、 server_handshake_traffic_secretから導出された鍵によって暗号化される。

4.4.1. 暗号化された 拡張

すべてのハンドシェイクで、サーバーは ServerHelloメッセージの直後に EncryptedExtensionsメッセージを送信しなければならない。 これは、server_handshake_traffic_secretから導出された鍵によって 暗号化される最初のメッセージである。

EncryptedExtensionsメッセージには、 保護できる拡張、すなわち、 暗号コンテキストの確立には不要であるが、 個々の証明書にも関連付けられていない拡張が含まれる。クライアントは、 EncryptedExtensionsに禁止されている 拡張が存在するか確認しなければならず、 見つかった場合は「illegal_parameter」アラートによってハンドシェイクを 中止しなければならない

このメッセージの構造は次のとおりである。

   struct {
       Extension extensions<0..2^16-1>;
   } EncryptedExtensions;
extensions:

拡張の一覧。詳細については、 第4.3節の表を参照されたい。

4.4.2. 証明書 要求

証明書によって認証するサーバーは、 クライアントに証明書を任意で 要求してもよい。このメッセージを送信する場合、 EncryptedExtensionsの後に 続けなければならない

このメッセージの構造は次のとおりである。

   struct {
       opaque certificate_request_context<0..2^8-1>;
       Extension extensions<0..2^16-1>;
   } CertificateRequest;
certificate_request_context:

証明書 要求を識別し、 クライアントのCertificateメッセージでエコーされるopaque文字列。 certificate_request_contextは、この接続の スコープ内で一意でなければならない (これにより、クライアントの CertificateVerifyメッセージのリプレイを防止する)。このフィールドは、 第4.7.2節で説明される ハンドシェイク後認証交換に使用されない限り、長さ0で なければならない。 ハンドシェイク後認証を要求する場合、サーバーは、 クライアントの秘密鍵へ一時的にアクセスできる攻撃者が 有効なCertificateVerifyメッセージを事前計算することを防ぐため、 コンテキストをクライアントにとって予測不能に (例えば、ランダムに生成して)することが望ましい

extensions:

要求される証明書のパラメーターを説明する 拡張の一覧。「signature_algorithms」 拡張を指定しなければならず、 このメッセージに対して定義されている場合、その他の拡張を 任意で含めることができる。 クライアントは認識できない拡張を無視しなければならない

以前のバージョンのTLSでは、CertificateRequestメッセージは、 サーバーが受け入れる署名アルゴリズムおよび認証局の一覧を 搬送していた。TLS 1.3では、前者は、 「signature_algorithms」および任意の「signature_algorithms_cert」 拡張を送信することで表される。後者は、 「certificate_authorities」拡張を送信することで 表される (第4.3.4節を参照)。

再開PSKによって認証するサーバーは、 メインハンドシェイクでCertificateRequestメッセージを 送信してはならない。ただし、 クライアントが「post_handshake_auth」拡張 (第 4.3.6節を参照)を送信している場合、 ハンドシェイク後認証(第4.7.2節を参照)で 送信してもよい。 これに反する別の仕様がない限り、 外部PSKによって認証するサーバーは、 メインハンドシェイクでCertificateRequestメッセージを 送信してはならず、 ハンドシェイク後認証を要求してはならない。 [RFC8773]はこれを許可する 拡張を提供するが、本仕様より分析が少ない。

4.5. 認証 メッセージ

第2節で説明したように、TLSは一般に、 認証、鍵確認、およびハンドシェイクの 完全性のために、Certificate、CertificateVerify、およびFinishedという 共通のメッセージ群を使用する。 (PSKバインダーも同様の方法で鍵確認を行う。)これら3つの メッセージは常に、各ハンドシェイク フライトの最後のメッセージとして送信される。CertificateおよびCertificateVerifyメッセージは、 以下で定義する特定の状況でだけ 送信される。Finished メッセージは常に認証ブロックの一部として送信される。 ハンドシェイク後認証を除き、これらのメッセージは、 [sender]_handshake_traffic_secretから導出された鍵によって 暗号化される。

認証メッセージの計算はすべて、 一様に次の入力を取る。

  • 使用する証明書および署名鍵。

  • トランスクリプトハッシュに 含めるメッセージの一覧からなるハンドシェイクコンテキスト。

  • MAC鍵の計算に使用するベース鍵。

これらの入力に基づき、各メッセージには次の内容が含まれる。

Certificate:

認証に使用する証明書、およびチェーン内の 補助証明書。証明書ベースの クライアント認証は、PSKハンドシェイクフロー (0-RTTを含む)では使用できないことに注意されたい。

CertificateVerify:

値Transcript-Hash(Handshake Context, Certificate)に対する署名。

Finished:

ベース鍵から導出されたMAC鍵を使用する、 値Transcript-Hash(Handshake Context, Certificate, CertificateVerify)に対するMAC。

次の表では、各シナリオについて、 ハンドシェイクコンテキストおよびMACベース鍵を定義する。

表2: 認証の入力
モード ハンドシェイクコンテキスト ベース鍵
サーバー ClientHello ... EncryptedExtensions/CertificateRequestのうち後のもの server_handshake_traffic_secret
クライアント ClientHello ... サーバーの Finished/EndOfEarlyDataのうち後のもの client_handshake_traffic_secret
ハンドシェイク後 ClientHello ... クライアントのFinished + CertificateRequest [sender]_application_traffic_​secret_N

4.5.1. 証明書

このメッセージは、エンドポイントの証明書チェーンをピアに伝達する。

合意された鍵交換方式が認証に証明書を使用する場合、 サーバーはCertificate メッセージを常に送信しなければならない (これには、PSKを除き、本文書で定義されるすべての鍵交換方式が含まれる)。

サーバーがCertificateRequestメッセージ (第4.4.2節)によって 証明書ベースのクライアント認証を要求した場合に限り、クライアントは Certificateメッセージを送信しなければならない。 サーバーが証明書ベースのクライアント認証を要求したが、 適切な証明書が利用できない場合、クライアントは 証明書を含まないCertificateメッセージ (すなわち、 「certificate_list」フィールドの長さが0)を 送信しなければならない。Certificateメッセージが空であるかどうかにかかわらず、 Finishedメッセージを送信しなければならない

このメッセージの構造は次のとおりである。

       enum {
           X509(0),
           RawPublicKey(2),
           (255)
       } CertificateType;

       struct {
           select (certificate_type) {
               case RawPublicKey:
                 /* RFC 7250のASN.1_subjectPublicKeyInfo */
                 opaque ASN1_subjectPublicKeyInfo<1..2^24-1>;

               case X509:
                 opaque cert_data<1..2^24-1>;
           };
           Extension extensions<0..2^16-1>;
       } CertificateEntry;

       struct {
           opaque certificate_request_context<0..2^8-1>;
           CertificateEntry certificate_list<0..2^24-1>;
       } Certificate;
certificate_request_context:

このメッセージがCertificateRequestへの応答である場合、 その メッセージ内のcertificate_request_contextの値。それ以外の場合 (サーバー認証の場合)、このフィールドは 長さ0でなければならない

certificate_list:

それぞれが 単一の証明書および拡張の一覧を含むCertificateEntry構造体の一覧(チェーン)。

extensions:

CertificateEntryに対する拡張値の一覧。 「Extension」 形式は第 4.3節で定義される。現時点でサーバー証明書に対して有効な拡張には、 OCSP Status拡張 [RFC6066]および SignedCertificateTimestamp拡張 [RFC6962]が含まれる。将来、 このメッセージに対してその他の拡張が定義される場合もある。サーバーからのCertificate メッセージ内の拡張は、ClientHelloメッセージ内の拡張に 対応しなければならない。 クライアントからのCertificateメッセージ内の拡張は、 サーバーからのCertificateRequestメッセージ内の拡張に 対応しなければならない。 拡張がチェーン全体に適用される場合、 最初のCertificateEntryに 含めることが望ましい

対応する証明書種類拡張 (「server_certificate_type」または「client_certificate_type」)が EncryptedExtensionsでネゴシエートされなかった場合、またはX.509証明書種類がネゴシエートされた場合、 各CertificateEntryにはDER符号化されたX.509証明書が含まれる。送信者の 証明書は、一覧の最初のCertificateEntryに 置かなければならない。後続の 各証明書は、直前の証明書を直接証明 することが望ましい。 証明書の検証では、トラストアンカーを 独立して配布する必要があるため、トラストアンカーを指定する証明書は、 サポートされるピアが省略された証明書を保持していることが 分かっている場合、チェーンから 省略してもよい

注: TLS 1.3より前では、「certificate_list」の順序は、 各証明書が 直前の証明書を証明することを要求していた。 ただし、一部の実装ではある程度の柔軟性を許可していた。サーバーは、 移行目的で現在の中間証明書と非推奨の中間証明書の両方を送信する場合があり、 単に設定が誤っている場合もあるが、それでもこれらの事例を 適切に検証できる可能性がある。最大限の互換性を得るため、すべての実装は、 任意のTLS バージョンからの余分な可能性がある証明書および任意の順序を 処理する用意があることが望ましい。 ただし、エンドエンティティ証明書は最初で なければならない

RawPublicKey証明書種類がネゴシエートされた場合、 certificate_listは 1つ以下のCertificateEntryを含まなければならず、 そのCertificateEntryには、 [RFC7250]の第 3節で定義されるASN1_subjectPublicKeyInfo値が含まれる。

OpenPGP証明書種類 [RFC6091]を TLS 1.3とともに使用してはならない

サーバーのcertificate_listは、 常に空であってはならない。クライアントは、 サーバーの認証 要求に応答して送信する適切な 証明書を持たない場合、空のcertificate_listを送信する。

4.5.1.1. OCSP ステータスおよびSCT拡張

[RFC6066]および[RFC6961]は、 サーバーがクライアントにOCSP応答を送信することをネゴシエートするための 拡張を提供する。TLS 1.2以前では、 サーバーは空の拡張で応答して、この 拡張がネゴシエートされたことを示し、OCSP情報はCertificateStatus メッセージで搬送される。TLS 1.3では、サーバーのOCSP情報は、 関連する証明書を含むCertificateEntry内の 拡張で搬送される。具体的には、サーバーからの「status_request」拡張の 本体は、[RFC6066]で定義される CertificateStatus構造体でなければならず[RFC6960]で定義されるとおりに解釈される。

注: status_request_v2拡張 [RFC6961]は非推奨である。TLS 1.3サーバーは、ClientHelloメッセージを処理する際、 その存在またはその中の情報に基づいて 動作してはならない。特に、 EncryptedExtensions、CertificateRequest、またはCertificateメッセージで status_request_v2拡張を送信してはならない。 TLS 1.3サーバーは、これを含むClientHello メッセージを処理できなければならない。 以前のプロトコルバージョンで使用することを望むクライアントが、 この拡張を送信してもよいためである。

サーバーは、CertificateRequestメッセージで空の 「status_request」拡張を送信することにより、 クライアントが証明書とともにOCSP応答を提示するよう 要求してもよい。クライアントがOCSP応答を送信することを選択した場合、 「status_request」拡張の本体は、 [RFC6066]で定義される CertificateStatus構造体でなければならない

同様に、[RFC6962]は、 TLS 1.2以前でサーバーが ServerHello内の拡張としてSigned Certificate Timestamp(SCT)を送信する 機構を提供する。 TLS 1.3では、サーバーのSCT情報は、 CertificateEntry内の拡張で搬送される。

4.5.1.2. 証明書 の選択

クライアントまたはサーバーが送信する証明書には、 次の規則が適用される。

  • 明示的に別の種類がネゴシエートされない限り (例えば、[RFC7250])、 証明書の種類はX.509v3 [RFC5280]なければならない

  • エンドエンティティ証明書は、 ピアの「signature_algorithms」拡張で示された署名方式を使用して 鍵で署名できるようにしなければならない第4.3.3節を参照)。すなわち、 Key Usage拡張が存在する場合、digitalSignatureビットを 設定しなければならず、 公開鍵(関連する制約を含む)は、 サポートされるいずれかの署名 方式と互換性がなければならない

  • ピアが「certificate_authorities」拡張を送信した場合、 証明書チェーン内の少なくとも1つの 証明書は、列挙された CAのいずれかによって発行されている ことが望ましい

クライアントが送信する証明書には、 さらに次の規則が適用される。

  • CertificateRequestメッセージに、 空でない「oid_filters」 拡張が含まれていた場合、エンドエンティティ証明書は、 クライアントが認識する拡張OIDと 一致しなければならない。 詳細は第4.3.5節を参照。

サーバーが送信する証明書には、 さらに次の規則が適用される。

  • 「server_name」拡張 [RFC6066]は、 証明書の 選択を導くために使用される。サーバーは、 「server_name」拡張の存在を要求してもよいため、 サーバーが名前によって識別される場合、クライアントは この拡張を送信することが望ましい

送信者が提供するすべての証明書は、 そのようなチェーンを提供できる場合、 ピアが広告した署名アルゴリズムによって 署名されていなければならない第 4.3.3節を参照)。 自己署名された 証明書、またはトラストアンカーとなることが想定される証明書は、 チェーンの一部として検証されないため、任意のアルゴリズムで 署名してもよい

送信者がサーバーであり、 示されたサポート対象アルゴリズムだけで署名された 証明書チェーンを生成できない場合、 サーバーは、クライアントがサポートすることが分かっていないアルゴリズムを含む可能性がある 任意の証明書チェーンを送信して、 ハンドシェイクを続行することが望ましい。 クライアントがSHA-1を受け入れる用意があることを明示的に広告していない限り、 このフォールバックチェーンは非推奨のSHA-1 ハッシュを使用してはならない

送信者がクライアントである場合、クライアントは、 上記のフォールバックチェーンを使用してもよく、 または匿名でハンドシェイクを続行してもよい。

受信者が提供された 証明書を使用して受け入れ可能なチェーンを構築できず、 ハンドシェイクを中止することを決定した場合、 適切な証明書関連のアラート (既定では「unsupported_certificate」。詳細については、 第6.2節を参照) によってハンドシェイクを中止しなければならない

送信者が複数の証明書を持つ場合、 上記の 基準(トランスポート層 エンドポイント、ローカル設定、選好などのその他の基準に加えて)に基づいて、 そのうち1つを選択する。

4.5.1.3. Certificateメッセージの受信

一般に、詳細な証明書検証手順は、 TLSの範囲外である ([RFC5280]を参照)。本 節では、TLS固有の要件を示す。

サーバーが空のCertificateメッセージを提供した場合、 クライアントは 「decode_error」アラートによってハンドシェイクを 中止しなければならない

クライアントが証明書を一切送信しない場合 (すなわち、空の Certificateメッセージを送信する場合)、 サーバーは裁量により、クライアント 認証なしでハンドシェイクを続行するか、 「certificate_required」アラートによってハンドシェイクを中止 してもよい。 また、 証明書チェーンの何らかの点が受け入れられない場合 (例えば、既知の信頼できるCAによって署名されていない場合)、 サーバーは裁量により、 ハンドシェイクを続行 (クライアントを未認証と見なす)するか、ハンドシェイクを中止 してもよい

MD5ハッシュを使用する署名アルゴリズムで 検証する必要がある証明書を受信したエンドポイントは、 「bad_certificate」アラートによって ハンドシェイクを中止しなければならない。 SHA-1は非推奨であり、 SHA-1ハッシュを使用する署名アルゴリズムで検証する必要がある 証明書を受信したエンドポイントは、 「bad_certificate」アラートによってハンドシェイクを中止することが 推奨される。明確にするため、 これは、自己署名証明書またはトラストアンカーである 証明書では、エンドポイントがこれらのアルゴリズムを受け入れられることを意味する。

現在SHA-1サポートを段階的に廃止している実装との 相互運用性を維持するため、すべてのエンドポイントは、 可能な限り早くSHA-256以上へ移行することが 推奨される

ある署名 アルゴリズム用の鍵を含む証明書が、 異なる署名アルゴリズムで 署名されてもよいことに注意されたい (例えば、ECDSA鍵で署名されたRSA鍵)。

4.5.2. 証明書検証

このメッセージは、エンドポイントが その証明書に対応する秘密鍵を保持していることを明示的に証明するために使用される。 CertificateVerifyメッセージは、 この時点までのハンドシェイクの完全性も提供する。サーバーは、 証明書によって認証する場合、このメッセージを 送信しなければならない。 クライアントは、証明書によって認証する場合 (すなわち、 Certificateメッセージが空でない場合)、常にこのメッセージを 送信しなければならない。送信する場合、このメッセージは Certificateメッセージの直後、 かつFinishedメッセージの直前に現れなければならない

このメッセージの構造は次のとおりである。

   struct {
       SignatureScheme algorithm;
       opaque signature<0..2^16-1>;
   } CertificateVerify;

algorithmフィールドは、使用される署名アルゴリズムを指定する (この型の定義については、 第4.3.3節を参照)。 signatureは、そのアルゴリズムを使用するデジタル署名である。 署名で対象となる内容は、 第4.1節で説明されるハッシュ出力、すなわち次のものである。

   Transcript-Hash(Handshake Context, Certificate)

その後、デジタル署名は、次のものを連結した値に対して計算される。

  • オクテット32(0x20)を64 回繰り返した文字列

  • コンテキスト文字列(以下で定義)

  • 区切りとして機能する単一の0バイト

  • 署名対象の内容

この構造は、以前のバージョン のTLSに対する攻撃を防止することを意図している。その攻撃では、 ServerKeyExchange形式のため、攻撃者が、選択した32バイトの 接頭辞(ClientHello.random)を持つメッセージの署名を取得できた。 最初の64バイトのパディングは、その接頭辞と、 サーバーが制御するServerHello.randomを消去する。

サーバー署名のコンテキスト文字列は "TLS 1.3, server CertificateVerify"である。 クライアント署名のコンテキスト文字列は "TLS 1.3, client CertificateVerify"である。 これは、異なるコンテキストで作成された署名を分離し、 潜在的なクロスプロトコル攻撃に対抗するために使用される。

例えば、トランスクリプトハッシュが 01の32バイト (この長さはSHA-256に適している)である場合、 サーバーのCertificateVerifyのデジタル署名で対象となる内容は次のようになる。

   2020202020202020202020202020202020202020202020202020202020202020
   2020202020202020202020202020202020202020202020202020202020202020
   544c5320312e332c207365727665722043657274696669636174655665726966
   79
   00
   0101010101010101010101010101010101010101010101010101010101010101

送信側では、CertificateVerifyメッセージの signatureフィールドを計算する処理は、次を入力として取る。

  • デジタル署名で対象となる内容

  • 直前の メッセージで送信された証明書に対応する署名用秘密鍵

CertificateVerifyメッセージがサーバーによって送信される場合、 サポートされていないアルゴリズムなしでは有効な証明書チェーンを生成できない場合を除き、 署名アルゴリズムは、クライアントの 「signature_algorithms」拡張で提示されたものの1つで なければならない第 4.3.3節を参照)。

クライアントによって送信される場合、 署名で使用される署名アルゴリズムは、 CertificateRequestメッセージ内の「signature_algorithms」拡張の supported_signature_algorithms フィールドに存在するものの1つで なければならない

さらに、署名アルゴリズムは、 送信者のエンドエンティティ証明書内の鍵と 互換性がなければならない。 SHA-1アルゴリズムを CertificateVerifyメッセージの署名で使用してはならない。 本仕様のすべてのSHA-1署名アルゴリズムは、 レガシー証明書での使用だけを目的として定義され、 CertificateVerify署名では有効でない。

CertificateVerifyメッセージの受信者は、 signatureフィールドを検証しなければならない。 検証処理は次を入力として取る。

  • デジタル署名で対象となる内容

  • 関連するCertificateメッセージ内で見つかった エンドエンティティ証明書に含まれる公開鍵

  • CertificateVerifyメッセージの signatureフィールドで受信したデジタル署名

検証に失敗した場合、受信者は 「decrypt_error」アラートによってハンドシェイクを 終了しなければならない

4.5.3. 完了

Finishedメッセージは認証 ブロック内の最後のメッセージである。ハンドシェイク および計算された鍵の認証を提供するために不可欠である。

Finishedメッセージの受信者は、 内容が 正しいことを検証しなければならず、正しくない場合は 「decrypt_error」アラートによって接続を 終了しなければならない

一方の側が自身のFinishedメッセージを送信し、 ピアからのFinishedメッセージを受信して 検証すると、接続上でApplication Dataの送受信を開始できる。 ピアのFinishedを受信する前に データを送信することが許可される状況は2つある。

  1. 第 4.3.10節で説明される0-RTTデータを送信するクライアント。

  2. サーバーは、最初のフライトを送信した後、 データを送信してもよい。ただし、 ハンドシェイクがまだ完了していないため、 ピアの識別情報または生存性 (すなわち、ClientHelloがリプレイされた可能性がある)の いずれについても保証されない。

Finishedメッセージの計算に使用される鍵は、 第4.5節で定義されるベース鍵から、 HKDF(第7.1節を参照)を使用して 計算される。具体的には次のとおりである。

finished_key =
    HKDF-Expand-Label(BaseKey, "finished", "", Hash.length)

このメッセージの構造は次のとおりである。

   struct {
       opaque verify_data[Hash.length];
   } Finished;

verify_data値は次のように計算される。

   verify_data =
       HMAC(finished_key,
            Transcript-Hash(Handshake Context,
                            Certificate*, CertificateVerify*))
*

存在する場合に限り含める。

HMAC [RFC2104]は、ハンドシェイク用のHashアルゴリズムを使用する。 上記のとおり、HMAC入力は通常、 実行中のハッシュ、すなわちこの時点のハンドシェイクハッシュだけで実装できる。

以前のバージョンのTLSでは、verify_dataは常に12オクテット の長さであった。 TLS 1.3では、ハンドシェイクで使用されるHashのHMAC出力のサイズである。

注: アラートおよびその他のハンドシェイクでないレコード種類は、 ハンドシェイクメッセージではなく、 ハッシュ計算には含まれない。

Finishedメッセージに続くすべてのレコードは、 第7.2節で説明される、 適切なアプリケーショントラフィック鍵によって 暗号化しなければならない。 特に、これには、クライアントのCertificateおよびCertificateVerifyメッセージに応答して サーバーが送信するすべてのアラートが含まれる。

4.6. 早期データの終了

   struct {} EndOfEarlyData;

サーバーがEncryptedExtensionsで「early_data」拡張を送信した場合、 クライアントはサーバーのFinishedを受信した後に EndOfEarlyDataメッセージを送信しなければならない。サーバーが EncryptedExtensionsで「early_data」拡張を送信しない場合、クライアントは EndOfEarlyDataメッセージを送信してはならない。このメッセージは、 0-RTT application_dataメッセージが存在する場合、それらがすべて送信され、 後続のレコードがハンドシェイクトラフィック鍵によって保護されることを示す。 サーバーはこのメッセージを送信してはならず、これを受信したクライアントは 「unexpected_message」アラートによって接続を 終了しなければならない。 このメッセージは、client_early_traffic_secretから導出された鍵によって暗号化される。

4.7. ハンドシェイク後 メッセージ

TLSでは、メインハンドシェイクの後にその他のメッセージを送信することもできる。 これらのメッセージはハンドシェイクコンテンツタイプを使用し、 適切なアプリケーショントラフィック鍵によって暗号化される。

4.7.1. 新しいセッション チケットメッセージ

クライアントのhelloに適切な「psk_key_exchange_modes」拡張が 含まれていた場合、サーバーはクライアントのFinishedメッセージを受信した後、 いつでもNewSessionTicketメッセージを 送信してもよい。 NewSessionTicketメッセージは、チケット値と、 再開秘密から導出された秘密PSKとの間に一意の関連付けを作成する (第7節を参照)。

クライアントは、将来のハンドシェイクでClientHelloの 「pre_shared_key」拡張にチケット値を含めることにより、 このPSKを使用してもよい第4.3.11節)。 NewSessionTicketメッセージを受信したが、 再開をサポートしないクライアントは、このメッセージを暗黙に 無視しなければならない。 元の接続がまだ開いている間に再開を 行ってもよい。サーバーは単一の接続で、 連続して、または特定のイベントの後に 複数のチケットを送信してもよい付録C.4を参照)。 例えば、サーバーはハンドシェイク後認証の後に新しいチケットを送信し、 追加のクライアント認証状態をカプセル化する場合がある。 複数のチケットは、次を含むさまざまな目的でクライアントに有用である。

  • 複数の並列HTTP接続を開く。

  • 例えば、Happy Eyeballs [RFC8305]または関連する技法を使用して、 インターフェイスおよびアドレスファミリー間で 接続競争を実行する。

チケットは、元の接続を確立するために使用したものと 同じKDFハッシュアルゴリズムを持つ暗号スイートでのみ 再開しなければならない

クライアントは、新しいSNI値が元のセッションで提示された サーバー証明書に対して有効な場合に限り 再開しなければならず、 SNI値が元のセッションで使用したものと一致する場合に限り 再開することが望ましい。後者は性能最適化である。 通常、単一の証明書でカバーされる異なるサーバーが、 相互のチケットを受け入れられると期待する理由はない。 したがって、その場合に再開を試みると、 使い捨てチケットを浪費することになる。 そのような指示が外部またはその他の手段で提供される場合、 クライアントは異なるSNI値で再開してもよい

再開時に、呼び出し元アプリケーションへSNI値を報告する場合、 実装は以前のセッションで送信された値ではなく、 再開ClientHelloで送信された値を 使用しなければならない。 サーバー実装が異なるSNI値を持つすべてのPSK識別情報を拒否する場合、 これら2つの値は常に同じであることに注意されたい。

注: 再開秘密はクライアントの2番目のフライトに依存するが、 証明書ベースのクライアント認証を要求しないサーバーは、 トランスクリプトの残りを独立して計算し、 クライアントのFinishedを待つ代わりに、 自身のFinishedを送信した直後にNewSessionTicketを 送信してもよい。 例えば、クライアントが複数のTLS接続を並列に開くことが予想され、 再開ハンドシェイクによるオーバーヘッド削減の恩恵を受ける場合に、 これは適切である可能性がある。

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

チケットの発行時点からの有効期間を秒単位で、 ネットワークバイト順の32ビット符号なし整数として示す。 サーバーは604800秒(7日)を超える値を 使用してはならない。 値0は、チケットを直ちに破棄すべきであることを示す。 クライアントは、ticket_lifetimeにかかわらず、 発行後7日を超えてチケットを 使用してはならず、 ローカルポリシーに基づいてチケットを早期に 削除してもよい。 サーバーは、ticket_lifetimeに記載された期間より短い期間だけ、 チケットを有効として扱ってもよい

ticket_age_add:

クライアントが「pre_shared_key」拡張に含める チケットの経過時間を不明瞭にするために使用する、 安全に生成されたランダムな32ビット値。 クライアント側のチケット経過時間をこの値に 232を法として加算し、 クライアントが送信する値を取得する。 サーバーは、送信する各チケットについて新しい値を 生成しなければならない

ticket_nonce:

この接続で発行されるすべてのチケット間で一意となる、 チケットごとの値。

ticket:

PSK識別情報として使用するチケットの値。 チケット自体はopaqueラベルである。 データベース検索鍵、または自己暗号化および自己認証された値の いずれであってもよい

extensions:

チケットに対する拡張値の一覧。 「Extension」形式は第 4.3節で定義される。クライアントは認識できない拡張を 無視しなければならない

現在NewSessionTicketに対して定義されている唯一の拡張は 「early_data」であり、チケットを0-RTTデータの送信に使用できることを示す (第4.3.10節)。 これには次の値が含まれる。

max_early_data_size:

このチケットを使用するときにクライアントが送信を許可される 0-RTTデータの最大量(バイト単位)。 Application Dataペイロードだけ (すなわち、平文。ただし、パディングまたは内部コンテンツタイプのバイトは含まない) を計数する。max_early_data_sizeバイトを超える0-RTTデータを受信したサーバーは、 「unexpected_message」アラートによって接続を 終了することが望ましい。 暗号素材がないために早期データを拒否するサーバーは、 パディングとコンテンツを区別できないことに注意されたい。 したがって、クライアントは早期データレコードで大量のパディングを送信できることに 依存しないことが望ましい

チケットに関連付けられるPSKは次のように計算される。

    HKDF-Expand-Label(resumption_secret,
                      "resumption", ticket_nonce, Hash.length)

ticket_nonce値は各NewSessionTicketメッセージで異なるため、 各チケットについて異なるPSKが導出される。

原理上、新しいチケットを発行し続けることで、 最初の非PSKハンドシェイクから導出された鍵素材 (ほとんどの場合、ピアの証明書に結び付けられている)の有効期間を 無期限に延長できることに注意されたい。 実装は、そのような鍵素材の総有効期間に制限を設けることが 推奨される。 これらの制限では、ピアの証明書の有効期間、 その間に失効する可能性、 およびピアがオンラインで行ったCertificateVerify署名からの経過時間を 考慮すべきである。

4.7.2. ハンドシェイク後 認証

クライアントが「post_handshake_auth」拡張を送信した場合 (第4.3.6節を参照)、 サーバーはハンドシェイクの完了後いつでも、 CertificateRequestメッセージを送信することにより、 証明書ベースのクライアント認証を 要求してもよい。 クライアントは適切な認証メッセージで 応答しなければならない第4.5節を参照)。 クライアントが認証を選択した場合、 Certificate、CertificateVerify、およびFinishedを 送信しなければならない。 拒否する場合、証明書を含まないCertificateメッセージを送信し、 その後にFinishedを送信しなければならない。 指定された応答に対するクライアントのすべてのメッセージは、 他の種類のメッセージまたは他の応答のメッセージを挟まず、 伝送路上で連続して現れなければならない

「post_handshake_auth」拡張を送信していないにもかかわらず、 ハンドシェイク後のCertificateRequestメッセージを受信したクライアントは、 致命的な「unexpected_message」アラートを 送信しなければならない

注: 証明書ベースのクライアント認証では、 ユーザーへの問い合わせが必要になる場合があるため、サーバーは、 CertificateRequestの送信から応答の受信までの間に、 任意の数のその他のメッセージを受信することを含む、 ある程度の遅延に備えなければならない。 さらに、短時間に複数のCertificateRequestを受信したクライアントは、 受信した順序とは異なる順序で 応答してもよい (certificate_request_context値により、サーバーは応答を区別できる)。

4.7.3. 鍵および 初期化ベクトルの更新

KeyUpdateハンドシェイクメッセージは、 送信者が送信用暗号鍵を更新していることを示すために使用される。 このメッセージは、いずれかのピアがFinishedメッセージを送信した後に送信できる。 Finishedメッセージを受信する前にKeyUpdateメッセージを受信した実装は、 「unexpected_message」アラートによって接続を 終了しなければならない。 KeyUpdateメッセージを送信した後、送信者は、 第7.2節で説明されているように計算された 次世代の鍵を使用して、すべてのトラフィックを 送信しなければならない。 KeyUpdateを受信した場合、受信者は受信用鍵を 更新しなければならない

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

   struct {
       KeyUpdateRequest request_update;
   } KeyUpdate;
request_update:

KeyUpdateの受信者が、 独自のKeyUpdateで応答すべきかどうかを示す。 実装がその他の値を受信した場合、 「illegal_parameter」アラートによって接続を 終了しなければならない

request_updateフィールドが「update_requested」に設定されている場合、 受信者は次のApplication Dataレコードを送信する前に、 request_updateを「update_not_requested」に設定した 独自のKeyUpdateを送信しなければならない。 この機構により、いずれの側も接続全体の更新を強制できるが、 無通信中に複数のKeyUpdateを受信した実装は、 1回の更新だけで応答する。 ピアから後続のKeyUpdateを受信するまで、 送信者はrequest_updateを「update_requested」に設定した別のKeyUpdateを 送信してはならない

request_updateを「update_requested」に設定したKeyUpdateを送信してから、 ピアのKeyUpdateを受信するまでの間に、 すでに転送中である可能性があるため、 関係のないKeyUpdateを含む任意の数のメッセージを受信する場合があることに注意されたい。 ただし、送信用鍵と受信用鍵は独立したトラフィック秘密から導出されるため、 受信用トラフィック秘密を保持しても、 送信者が鍵を変更する前に送信されたデータの前方秘匿性を脅かすことはない。

実装がrequest_updateを「update_requested」に設定した 独自のKeyUpdateをそれぞれ独立して送信し、 それらが転送中に交差した場合、 各側はさらに応答を送信し、その結果、 各側が2世代分進む。

送信者および受信者は、いずれも古い鍵で KeyUpdateメッセージを暗号化しなければならない。 さらに、両側は、新しい鍵で暗号化されたメッセージを受け入れる前に、 古い鍵によるKeyUpdateを受信したことを 保証しなければならない。 これを行わない場合、メッセージ切り詰め攻撃が可能になることがある。

AES-128のような128ビット鍵では、 264回の鍵更新を行うと、 指定された接続内で鍵が再利用される確率が高くなる。 鍵が繰り返されても、IVは独立して生成されるため、 鍵とIVが同時に衝突する確率ははるかに低いことに注意されたい。 追加のセキュリティ余裕を提供するため、送信側実装は、 エポック、したがって鍵更新回数が248-1を超えることを 許可してはならない。 例えば128ビットを超える鍵を持つ暗号のために、 この値を後で変更できるようにするため、 受信側実装はこの規則を 強制してはならない。 送信側実装がrequest_updateを「update_requested」に設定したKeyUpdateを受信した場合、 自身のKeyUpdateを送信するとこれらの制限を超えるなら、 それを送信してはならず、 代わりに「update_requested」フラグを 無視することが望ましい。 これにより、第5.5節の 制限に達したとき、最終的に接続を終了する必要が生じる場合がある。

5. レコードプロトコル

TLSレコードプロトコルは、送信するメッセージを受け取り、データを 管理可能なブロックに断片化し、レコードを保護して、その結果を 送信する。受信したデータは検証、復号、再構成され、 その後、上位レベルのクライアントに渡される。

TLSレコードには型があり、同じレコード層上で複数の上位レベルプロトコルを 多重化できる。本文書では、 handshake、application_data、alert、および change_cipher_specという4つのコンテンツタイプを規定する。 change_cipher_specレコードは、互換性を目的としてのみ使用される (付録E.4を参照)。

実装は、最初のClientHelloメッセージを送信または受信した後、 ピアのFinishedメッセージを受信するまでの任意の時点で、 単一バイト値0x01からなる暗号化されていない change_cipher_spec型のレコードを受信する場合があり、 追加処理を行わず単に破棄しなければならない。 このレコードは、実装が保護されたレコードを想定している ハンドシェイク上の時点に現れる可能性があるため、 レコードの保護解除を試みる前に、この 状態を検出する必要があることに注意されたい。 その他のchange_cipher_spec値を受信した実装、または 保護されたchange_cipher_specレコードを受信した実装は、 「unexpected_message」アラートによってハンドシェイクを 中止しなければならない。実装が、 最初のClientHelloメッセージより前、またはピアのFinished メッセージより後に受信したchange_cipher_specレコードを検出した場合、 予期しないレコード型として扱わなければならない (ただし、ステートレスなサーバーは、これらの場合と許可される場合を区別できないことがある)。

実装は、何らかの拡張によってネゴシエートされない限り、 本文書で定義されていないレコード型を 送信してはならない。 TLS実装が予期しないレコード型を受信した場合、 「unexpected_message」アラートによって接続を 終了しなければならない。 新しいレコードコンテンツタイプ値は、 第11節で説明されているように、 TLS ContentTypeレジストリでIANAによって割り当てられる。

5.1. レコード層

レコード層は、情報ブロックを214バイト以下の データチャンクを搬送するTLSPlaintextレコードに断片化する。 メッセージ境界は、基礎となる ContentTypeに応じて異なる方法で処理される。 将来のコンテンツタイプは、適切な規則を 規定しなければならない。 これらの規則は、TLS 1.2で強制されていたものより厳格であることに注意されたい。

ハンドシェイクメッセージは、次の条件を満たす限り、 単一のTLSPlaintextレコードに結合 してもよく、 または複数のレコードにまたがって断片化してもよい。

  • ハンドシェイクメッセージは、その他のレコード型と 交互に配置してはならない。 すなわち、ハンドシェイクメッセージが2つ以上の レコードに分割される場合、それらの間にその他のレコードが 存在してはならない

  • ハンドシェイクメッセージは、鍵の変更をまたいで はならない。 実装は、鍵の変更の直前にあるすべてのメッセージが レコード境界に揃っていることを検証しなければならず、 そうでない場合、 「unexpected_message」アラートによって接続を 終了しなければならない。 ClientHello、EndOfEarlyData、ServerHello、Finished、および KeyUpdateメッセージは、鍵の変更の直前に現れる可能性があるため、 実装はこれらのメッセージをレコード境界に揃えて 送信しなければならない

実装は、パディングを含む場合でも、 Handshake型の長さ0の断片を 送信してはならない

アラートメッセージ(第 6節)は、複数のレコードにまたがって 断片化してはならず、 複数のアラートメッセージを単一のTLSPlaintextレコードに 結合してはならない。 すなわち、Alert型のレコードは 正確に1つのメッセージを含まなければならない

Application Dataメッセージには、 TLSにとってopaqueなデータが含まれる。 Application Dataメッセージは常に保護される。 Application Dataの長さ0の断片 (すなわち、contentが長さ0である application_data型のTLSInnerPlaintextレコード)は、 トラフィック分析への対策として有用である可能性があるため、 送信してもよい。 Application Dataの断片は、複数のレコードに分割してもよく、 単一のレコードに結合してもよい。

   enum {
       invalid(0),
       change_cipher_spec(20),
       alert(21),
       handshake(22),
       application_data(23),
       (255)
   } ContentType;

   struct {
       ContentType type;
       ProtocolVersion legacy_record_version;
       uint16 length;
       opaque fragment[TLSPlaintext.length];
   } TLSPlaintext;
type:

包含された断片を処理するために使用する上位レベルプロトコル。

legacy_record_version:

最初のClientHello (すなわち、HelloRetryRequestの後に生成されたものではない) 以外のTLS 1.3実装によって生成されるすべてのレコードでは、 0x0303に設定しなければならない。 最初のClientHelloでは、互換性を目的として 0x0301であってもよい。 このフィールドは非推奨であり、あらゆる目的で 無視しなければならない。 以前のバージョンのTLSでは、 一部の状況でこのフィールドにその他の値を使用していた。

length:

後続するTLSPlaintext.fragmentの長さ (バイト単位)。 長さは214バイトを 超えてはならない。 この長さを超えるレコードを受信したエンドポイントは、 「record_overflow」アラートによって接続を 終了しなければならない

fragment

送信されるデータ。この値は透過的であり、 typeフィールドで指定される上位レベルプロトコルによって 処理される独立したブロックとして扱われる。

本文書では、バージョン0x0304を使用するTLS 1.3を説明する。 このバージョン値は歴史的なものであり、 TLS 1.0で0x0301、SSL 3.0で0x0300を使用したことに由来する。 後方互換性を最大化するため、最初のClientHelloを含むレコードの versionは0x0301 (TLS 1.0を表す)であることが望ましく、 2番目のClientHelloまたはServerHelloを含むレコードのversionは 0x0303(TLS 1.2を表す)で なければならない。 以前のバージョンのTLSをネゴシエートする場合、エンドポイントは 付録Eで示される手順および要件に従う。

レコード保護がまだ有効になっていない場合、 TLSPlaintext構造体は直接伝送路に書き込まれる。 レコード保護が開始された後、TLSPlaintextレコードは、 次の節で説明するように保護され、送信される。 Application Dataレコードは、保護されていない状態で伝送路に 書き込んではならないことに注意されたい (詳細については、第2節を参照)。

5.2. レコードペイロード の保護

レコード保護関数は、TLSPlaintext構造体を TLSCiphertext構造体に変換する。保護解除関数はこの処理を逆に行う。 以前のバージョンのTLSとは異なり、TLS 1.3では、 すべての暗号が「関連データ付き認証暗号」 (AEAD)[RFC5116]としてモデル化される。 AEAD関数は、平文を認証済み暗号文に変換し、 元に戻す、統合された暗号化および認証処理を提供する。 各暗号化レコードは、平文ヘッダーと、 その後に続く暗号化された本体からなる。 本体自体には、型および任意のパディングが含まれる。

   struct {
       opaque content[TLSPlaintext.length];
       ContentType type;
       uint8 zeros[length_of_padding];
   } TLSInnerPlaintext;

   struct {
       ContentType opaque_type = application_data; /* 23 */
       ProtocolVersion legacy_record_version = 0x0303; /* TLS v1.2 */
       uint16 length;
       opaque encrypted_record[TLSCiphertext.length];
   } TLSCiphertext;
content:

ハンドシェイクまたはアラートメッセージのバイト符号化、 あるいは送信するアプリケーションデータの生のバイトを含む、 TLSPlaintext.fragment値。

type:

レコードのコンテンツタイプを含むTLSPlaintext.type値。

zeros:

typeフィールドの後の平文に、 任意長の0値バイト列が現れてもよい。 これにより、合計がレコードサイズ制限内に収まる限り、 送信者は任意のTLSレコードを選択した量だけ パディングできる。詳細については、 第5.4節を参照されたい。

opaque_type:

TLSCiphertextレコードの外側のopaque_typeフィールドは、 以前のバージョンのTLSを解析することに慣れた ミドルボックスとの外部互換性のため、 常に値23(application_data)に設定される。 レコードの実際のコンテンツタイプは、復号後の TLSInnerPlaintext.typeで確認される。

legacy_record_version:

legacy_record_versionフィールドは常に0x0303である。 TLS 1.3のTLSCiphertextは、 TLS 1.3がネゴシエートされた後まで生成されないため、 その他の値を受信する可能性がある歴史的な互換性上の問題はない。 ClientHelloおよびServerHelloメッセージを含む ハンドシェイクプロトコルがプロトコルバージョンを認証するため、 この値は冗長であることに注意されたい。

length:

後続するTLSCiphertext.encrypted_recordの長さ (バイト単位)。 これはcontentとpaddingの長さの合計に、 内部コンテンツタイプ用の1バイト、 およびAEADアルゴリズムによって追加される拡張分を加えたものである。 長さは214 + 256バイトを 超えてはならない。 この長さを超えるレコードを受信したエンドポイントは、 「record_overflow」アラートによって接続を 終了しなければならない

encrypted_record:

シリアライズされたTLSInnerPlaintext構造体を AEADで暗号化した形式。

AEADアルゴリズムは、 [RFC5116]の第2.1節で説明されているように、 単一の鍵、ノンス、平文、および認証検査に含める 「追加データ」を入力として取る。 鍵はclient_write_keyまたはserver_write_keyであり、 ノンスはシーケンス番号と client_write_ivまたはserver_write_ivから導出され (第5.3節を参照)、 追加データ入力はレコードヘッダーである。すなわち、

   additional_data = TLSCiphertext.opaque_type ||
                     TLSCiphertext.legacy_record_version ||
                     TLSCiphertext.length

AEADアルゴリズムへの平文入力は、 符号化されたTLSInnerPlaintext構造体である。 トラフィック鍵の導出は、第7.3節で定義される。

AEAD出力は、AEAD暗号化処理から得られる暗号文出力からなる。 TLSInnerPlaintext.typeおよび送信者が提供する パディングが含まれるため、平文の長さは、 対応するTLSPlaintext.lengthより大きい。 AEAD出力の長さは一般に平文より大きいが、 その差はAEADアルゴリズムによって異なる。 暗号がパディングを組み込む場合があるため、 オーバーヘッド量は平文の長さによって異なる可能性がある。 記号的には、

   AEADEncrypted =
       AEAD-Encrypt(write_key, nonce, additional_data, plaintext)

TLSCiphertextのencrypted_recordフィールドはAEADEncryptedに設定される。

復号および検証のため、暗号は、 鍵、ノンス、追加データ、およびAEADEncrypted値を入力として取る。 出力は平文、または復号に失敗したことを示すエラーのいずれかである。 個別の完全性検査は存在しない。記号的には、

 plaintext of encrypted_record =
     AEAD-Decrypt(peer_write_key, nonce, additional_data, AEADEncrypted)

復号に失敗した場合、受信者は 「bad_record_mac」アラートによって接続を 終了しなければならない

TLS 1.3で使用するAEADアルゴリズムは、 255オクテットを超える拡張を 生成してはならない。 ピアからTLSCiphertext.lengthが 214 + 256オクテットを超えるレコードを受信したエンドポイントは、 「record_overflow」アラートによって接続を 終了しなければならない。 この制限は、TLSInnerPlaintextの最大長である 214オクテット、ContentType用の1オクテット、 およびAEADの最大拡張量255オクテットから導かれる。

5.3. レコードごとのノンス

64ビットのシーケンス番号は、レコードの読み取り用と書き込み用に 個別に維持される。適切なシーケンス番号は、 各レコードの読み取りまたは書き込み後に1ずつ増加する。 各シーケンス番号は、接続の開始時および鍵が変更されるたびに0に設定される。 特定のトラフィック鍵で送信される最初のレコードは、 シーケンス番号0を使用しなければならない

シーケンス番号のサイズは64ビットであるため、 ラップアラウンドすべきではない。 TLS実装でシーケンス番号をラップアラウンドさせる必要が生じる場合、 鍵を更新する (第4.7.3節)か、 接続を終了するかのいずれかを 行わなければならない

各AEADアルゴリズムは、 レコードごとのノンスに使用可能な長さの範囲を、 N_MINバイトからN_MAXバイトまでの入力として規定する [RFC5116]。 TLSのレコードごとのノンスの長さ (iv_length)は、8バイトとAEADアルゴリズムのN_MINのうち、 大きい方に設定される ([RFC5116]の第4節を参照)。 N_MAXが8バイト未満であるAEADアルゴリズムを TLSで使用してはならない。 AEAD構成のレコードごとのノンスは次のように形成される。

  1. 64ビットのレコードシーケンス番号を ネットワークバイト順で符号化し、 iv_lengthになるまで左側を0でパディングする。

  2. パディングされたシーケンス番号を、 役割に応じて静的なclient_write_ivまたは server_write_ivのいずれかとXORする。

得られた値 (長さiv_length)をレコードごとのノンスとして使用する。

注: これは、部分的に明示的なノンスを規定していた TLS 1.2の構成とは異なる。

5.4. レコードパディング

暗号化されたすべてのTLSレコードは、 TLSCiphertextのサイズを増加させるためにパディングできる。 これにより、送信者はトラフィックのサイズを観測者から隠すことができる。

TLSCiphertextレコードを生成する際、実装は パディングすることを選択してもよい。 パディングされていないレコードは、 単にパディング長が0のレコードである。 パディングは、暗号化前にContentTypeフィールドの後に付加される 0値バイトの文字列である。 実装は、暗号化前にパディングオクテットをすべて0に 設定しなければならない

送信者が望む場合、Application Dataレコードは、 長さ0のTLSInnerPlaintext.contentを含んでもよい。 これにより、活動の有無が機微である可能性のある状況で、 妥当なサイズのカバートラフィックを生成できる。 実装は、長さ0のTLSInnerPlaintext.contentを持つ HandshakeおよびAlertレコードを 送信してはならない。 そのようなメッセージを受信した場合、受信側実装は、 「unexpected_message」アラートによって接続を 終了しなければならない

送信されたパディングは、レコード保護機構によって自動的に検証される。 TLSCiphertext.encrypted_recordの復号に成功すると、 受信側実装は、0でないオクテットが見つかるまで、 フィールドの末尾から先頭方向に走査する。 この0でないオクテットがメッセージのコンテンツタイプである。 このパディング方式は、新しいコンテンツタイプを導入せずに、 暗号化された任意のTLSレコードを任意のサイズ (0からTLSレコードサイズ制限まで)でパディングできるため選択された。 また、この設計は、すべて0のパディングオクテットを強制し、 パディングエラーを迅速に検出できるようにする。

実装は、AEAD復号から返された平文だけに 走査範囲を制限しなければならない。 受信側実装が平文内に0でないオクテットを見つけられない場合、 「unexpected_message」アラートによって接続を 終了しなければならない

パディングの存在によって、レコード全体のサイズ制限は変わらない。 符号化されたTLSInnerPlaintext全体は、 214 + 1オクテットを 超えてはならない。 例えば、[RFC8449]の record_size_limit拡張によって最大断片長が削減された場合、 削減後の制限は、コンテンツタイプおよびパディングを含む 平文全体に適用される。

いつ、どの程度パディングするかを示す パディングポリシーの選択は複雑な問題であり、 本仕様の範囲外である。 TLS上のアプリケーション層プロトコルが独自のパディングを持つ場合、 Application DataのTLSレコードは、アプリケーション層内で パディングする方が望ましい場合がある。 ただし、暗号化されたHandshakeまたはAlertレコードのパディングは、 引き続きTLS層で処理する必要がある。 将来の文書で、パディング選択アルゴリズム、 またはTLS拡張やその他の手段を介した パディングポリシー要求機構が定義される場合がある。

5.5. 鍵使用の制限

指定された鍵の組で安全に暗号化できる 平文の量には暗号学的な制限がある。 [AEAD-LIMITS]は、 基礎となるプリミティブ (AESまたはChaCha20)に弱点がないという仮定の下で、 これらの制限を分析している。 実装は、これらの制限に達する前に、 接続を閉じるか、第 4.7.3節で説明されている鍵更新を行うかのいずれかを 実行しなければならない。 早期データではKeyUpdateを実行できないことに注意されたい。 したがって、実装は早期データを送信する際、 これらの制限を超えてはならない。 将来の分析によって値が更新される可能性があるため、 受信側実装はこれらの制限を 強制しないことが望ましい

AES-GCMでは、認証暗号 (AE)セキュリティについて約2-57の安全余裕を維持しながら、 指定された鍵の組で、最大224.5個のフルサイズレコード (約2400万個)を暗号化できる。 ChaCha20/Poly1305では、安全限界に達する前に レコードシーケンス番号がラップアラウンドする。

6. アラートプロトコル

TLSは、終了情報およびエラーを示すためのAlertコンテンツタイプを 提供する。他のメッセージと同様に、アラートメッセージは 現在の接続状態によって規定されるとおりに暗号化される。

アラートメッセージは、アラートの説明と、以前のバージョンの TLSでメッセージの深刻度を伝達していたレガシーフィールドを搬送する。 アラートは、 終了アラートとエラーアラートの2つのクラスに分けられる。TLS 1.3では、 深刻度は送信されるアラートの種類に暗黙的に含まれ、 「level」フィールドは安全に無視できる。「close_notify」アラートは、 接続の一方向が正常に終了することを示すために使用される。 このようなアラートを受信した場合、TLS実装は アプリケーションにデータの終了を示すことが望ましい

エラーアラートは、接続が異常終了したことを示す (第6.2節を参照)。エラーアラートを受信した場合、 TLS実装はアプリケーションにエラーを示すことが 望ましく、 接続上でそれ以上のデータの送受信を 許可してはならない。サーバーおよびクライアントは、 失敗した接続で確立された秘密値および鍵を 破棄しなければならない。ただし、 セッションチケットに関連付けられたPSKは例外であり、 可能であれば破棄することが望ましい

第 6.2節に列挙されているすべてのアラートは、 AlertLevel=fatalで送信しなければならず、 メッセージ内のAlertLevelにかかわらず、 受信時にはエラーアラートとして扱わなければならない。 未知のAlert種類は、エラーアラートとして扱わなければならない

注: TLSは、メッセージの解析に失敗した場合に使用する 2つの汎用アラート(第6節を参照)を定義している。 構文に従って解析できないメッセージ (例えば、長さがメッセージ境界を超えているものや、 範囲外の長さを含むもの)を受信したピアは、 「decode_error」アラートによって接続を 終了しなければならない。 構文的には正しいが意味的に無効なメッセージ (例えば、p - 1のDHE共有値や無効なenum)を受信したピアは、 「illegal_parameter」アラートによって接続を 終了しなければならない

   enum { warning(1), fatal(2), (255) } AlertLevel;

   enum {
       close_notify(0),
       unexpected_message(10),
       bad_record_mac(20),
       record_overflow(22),
       handshake_failure(40),
       bad_certificate(42),
       unsupported_certificate(43),
       certificate_revoked(44),
       certificate_expired(45),
       certificate_unknown(46),
       illegal_parameter(47),
       unknown_ca(48),
       access_denied(49),
       decode_error(50),
       decrypt_error(51),
       protocol_version(70),
       insufficient_security(71),
       internal_error(80),
       inappropriate_fallback(86),
       user_canceled(90),
       missing_extension(109),
       unsupported_extension(110),
       unrecognized_name(112),
       bad_certificate_status_response(113),
       unknown_psk_identity(115),
       certificate_required(116),
       general_error(117),
       no_application_protocol(120),
       (255)
   } AlertDescription;

   struct {
       AlertLevel level;
       AlertDescription description;
   } Alert;

6.1. 終了アラート

切り詰め攻撃を回避するため、クライアントとサーバーは、 接続が終了することを共有して認識する必要がある。

close_notify:

このアラートは、送信者がこの接続上で これ以上メッセージを送信しないことを受信者に通知する。 終了アラートを受信した後に受信したデータは、 無視しなければならない。このアラートは AlertLevel=warningで送信しなければならない

user_canceled:

このアラートは、プロトコル障害とは無関係の何らかの理由で、 送信者がハンドシェイクを取り消していることを受信者に通知する。 ハンドシェイクの完了後にユーザーが操作を取り消した場合は、 「close_notify」を送信して接続を閉じる方が適切である。 このアラートの後には「close_notify」を 続けなければならない。このアラートは通常、 AlertLevel=warningである。受信側実装は、 「close_notify」を受信するまでピアからデータを 読み続けることが望ましいが、 それらをログに記録するなどして 記録してもよい

いずれの当事者も、「close_notify」アラートを送信することにより、 接続の書き込み側の終了を 開始してもよい。 「close_notify」より前にトランスポート層の終了を受信した場合、 受信者は送信されたすべてのデータが受信されたかどうかを確認できない。

各当事者は、すでに何らかのエラーアラートを送信している場合を除き、 接続の書き込み側を閉じる前に「close_notify」アラートを 送信しなければならない。 これは接続の読み取り側には影響しない。 これはTLS 1.3より前のバージョンからの変更であることに注意されたい。 以前のバージョンでは、実装は「close_notify」に応答して、 保留中の書き込みを破棄し、 自身の「close_notify」アラートを直ちに送信する必要があった。 以前の要件は、読み取り側で切り詰めを引き起こす可能性があった。 両当事者は、接続の読み取り側を閉じる前に 「close_notify」アラートを受信するまで待つ必要はないが、 待たない場合は切り詰めの可能性が生じる。

アプリケーションプロトコルは、「close_notify」を受信したときに、 送信バッファをフラッシュし、直ちに「close_notify」を送信することを 選択してもよい。 ただし、これにより攻撃者は、「close_notify」を遅延させたり、 アプリケーションパケットのトランスポート層での配送を遅延させたりすることで、 ピアが受信するデータに影響を与えられる。 これらの問題は、例えば「close_notify」の送信後に受信したパケットを 無視することにより、アプリケーション層で対処できる。

TLSを使用するアプリケーションプロトコルが、 TLS接続の終了後に基礎となるトランスポート上で何らかのデータを搬送できると規定する場合、 TLS実装は、アプリケーション層にデータの終了を示す前に、 「close_notify」アラートを受信しなければならない。 本標準のいかなる部分も、接続をいつ開閉するかを含め、 TLSの使用プロファイルがデータトランスポートを管理する方法を 規定するものと解釈すべきではない。

注: 接続の書き込み側を閉じると、 トランスポートを破棄する前に保留中のデータが確実に配送されるものと想定する。

6.2. エラーアラート

TLSのエラー処理は非常に単純である。 エラーが検出されると、検出した当事者はピアにメッセージを送信する。 致命的なアラートメッセージを送信または受信すると、 両当事者は直ちに接続を 閉じなければならない

実装が致命的なエラー状態に遭遇した場合、 適切な致命的アラートを送信することが 望ましく、 追加のデータを送受信せずに接続を 閉じなければならない。 本仕様全体で、特定のアラートを指定せずに 「接続を終了する」および「ハンドシェイクを中止する」という表現を使用する場合、 実装が以下の説明で示されるアラートを送信することが 望ましいことを意味する。 「Xアラートによって接続を終了する」および 「Xアラートによってハンドシェイクを中止する」という表現は、 実装が何らかのアラートを送信する場合、 アラートXを送信しなければならないことを意味する。 本節で以下に定義されるすべてのアラート、およびすべての未知のアラートは、 TLS 1.3以降、常に致命的であると見なされる (第6節を参照)。 実装は、アラートの送受信をログに記録しやすくする方法を 提供することが望ましい

次のエラーアラートが定義される。

unexpected_message:

不適切なメッセージ (例えば、誤ったハンドシェイクメッセージ、 時期尚早なApplication Dataなど)を受信した。 このアラートは、適正な実装間の通信では決して 観測されないはずである。

bad_record_mac:

保護解除できないレコードを受信した場合に、このアラートが返される。 AEADアルゴリズムは復号と検証を組み合わせており、 またサイドチャネル攻撃を回避するため、 このアラートはすべての保護解除失敗に使用される。 このアラートは、ネットワーク内でメッセージが破損した場合を除き、 適正な実装間の通信では決して観測されないはずである。

record_overflow:

長さが214 + 256バイトを超える TLSCiphertextレコードを受信したか、 レコードを復号した結果、214バイト (またはその他のネゴシエートされた制限)を超える TLSPlaintextレコードになった。 このアラートは、ネットワーク内でメッセージが破損した場合を除き、 適正な実装間の通信では決して観測されないはずである。

handshake_failure:

「handshake_failure」アラートメッセージの受信は、 利用可能な選択肢を考慮しても、 送信者が受け入れ可能なセキュリティパラメーター群を ネゴシエートできなかったことを示す。

bad_certificate:

証明書が破損していた、正しく検証できない署名を含んでいた、など。

unsupported_certificate:

証明書がサポートされていない種類であった。

certificate_revoked:

証明書が署名者によって失効された。

certificate_expired:

証明書の有効期限が切れているか、現在有効ではない。

certificate_unknown:

証明書の処理中にその他の (未指定の)問題が発生し、証明書を受け入れられなくなった。

illegal_parameter:

ハンドシェイク内のフィールドが不正であるか、 その他のフィールドと整合していなかった。 このアラートは、形式的なプロトコル構文には適合するが、 その他の点で不正なエラーに使用される。

unknown_ca:

有効な証明書チェーンまたは部分チェーンを受信したが、 CA証明書を見つけられないか、 既知のトラストアンカーと照合できなかったため、 証明書が受け入れられなかった。

access_denied:

有効な証明書またはPSKを受信したが、 アクセス制御を適用した結果、 送信者がネゴシエーションを続行しないことを決定した。

decode_error:

一部のフィールドが指定された範囲外であるか、 メッセージの長さが不正であるため、 メッセージを復号できなかった。 このアラートは、メッセージが形式的なプロトコル構文に 適合しないエラーに使用される。 このアラートは、ネットワーク内でメッセージが破損した場合を除き、 適正な実装間の通信では決して観測されないはずである。

decrypt_error:

署名の正しい検証、Finishedメッセージの検証、 またはPSKバインダーの検証ができないことを含め、 ハンドシェイク (レコード層ではない)の暗号処理に失敗した。

protocol_version:

ピアがネゴシエートしようとしたプロトコルバージョンは 認識されているが、サポートされていない (付録Eを参照)。

insufficient_security:

サーバーがクライアントのサポートするものより 安全なパラメーターを要求したことが原因で ネゴシエーションに失敗した場合、 「handshake_failure」の代わりに返される。

internal_error:

ピアまたはプロトコルの正しさとは無関係の内部エラー (メモリ割り当ての失敗など)により、 続行できなくなった。

inappropriate_fallback:

クライアントからの無効な接続再試行に応答して、 サーバーによって送信される ([RFC7507]を参照)。

missing_extension:

提示されたTLSバージョンまたはその他の ネゴシエートされたパラメーターについて、 送信が必須である拡張を含まない ハンドシェイクメッセージを受信したエンドポイントによって送信される。

unsupported_extension:

対応するClientHelloまたはCertificateRequestで 最初に提示されていない拡張を、 ServerHello、HelloRetryRequest、EncryptedExtensions、 またはCertificate内に含む ハンドシェイクメッセージを受信したエンドポイントによって送信される。

unrecognized_name:

クライアントが「server_name」拡張によって提供した名前で 識別されるサーバーが存在しない場合に、 サーバーによって送信される ([RFC6066]を参照)。

bad_certificate_status_response:

サーバーが「status_request」拡張によって 無効または受け入れられないOCSP応答を提供した場合に、 クライアントによって送信される ([RFC6066]を参照)。

unknown_psk_identity:

PSK鍵確立が必要であるが、 クライアントから受け入れ可能なPSK識別情報が提供されなかった場合に、 サーバーによって送信される。 このアラートの送信は任意である。 サーバーは代わりに、無効なPSK識別情報であることだけを示すために、 「decrypt_error」アラートを送信することを 選択してもよい

certificate_required:

クライアント証明書が必要であるが、 クライアントによって提供されなかった場合に、 サーバーによって送信される。

general_error:

より具体的なエラーが利用できない場合、 または送信者が具体的なエラーコードを隠すことを望む場合に、 エラー状態を示すために送信される。 実装は、利用可能な場合はより具体的なエラーを 使用することが望ましい

no_application_protocol:

クライアントの 「application_layer_protocol_negotiation」拡張が、 サーバーのサポートしないプロトコルだけを広告している場合に、 サーバーによって送信される ([RFC7301]を参照)。

新しいAlert値は、第11節で説明されているように、 IANAによって割り当てられる。

7. 暗号学的計算

TLSハンドシェイクは、以下で詳述するように、 実際に使用する鍵素材を作成するために組み合わせる 1つ以上の入力秘密を確立する。 鍵導出処理には、入力秘密とハンドシェイクトランスクリプトの両方が組み込まれる。 ハンドシェイクトランスクリプトにはHelloメッセージのランダム値が含まれるため、 同じPSKを複数の接続で使用する場合のように、 同じ入力秘密を使用した場合でも、 各ハンドシェイクは異なるトラフィック秘密を持つことに注意されたい。

7.1. 鍵スケジュール

鍵導出処理では、HKDF [RFC5869]で定義される HKDF-Extract関数およびHKDF-Expand関数と、 以下で定義する関数を使用する。

    HKDF-Expand-Label(Secret, Label, Context, Length) =
         HKDF-Expand(Secret, HkdfLabel, Length)

ここで、HkdfLabelは次のように規定される。

    struct {
        uint16 length = Length;
        opaque label<7..255> = "tls13 " + Label;
        opaque context<0..255> = Context;
    } HkdfLabel;

    Derive-Secret(Secret, Label, Messages) =
         HKDF-Expand-Label(Secret, Label,
                           Transcript-Hash(Messages), Hash.length)

Transcript-HashおよびHKDFで使用されるHash関数は、 暗号スイートのハッシュアルゴリズムである。 Hash.lengthは、その出力長をバイト単位で表す。 Messagesは、示されたハンドシェイクメッセージを連結したものであり、 ハンドシェイクメッセージの種類および長さフィールドを含むが、 レコード層ヘッダーは含まない。 場合によっては、長さ0のContext (「」で示される)がHKDF-Expand-Labelに渡されることに注意されたい。 本文書で規定されるラベルはすべてASCII文字列であり、 末尾のNULバイトを含まない。

「HKDF-Expand-Label」を使用するTLSの拡張は、 使用されるTLSバージョンに関連付けられた HkdfLabel定義を使用する。 本仕様とともに使用する場合は、上記で定義したHkdfLabelを使用することを意味する。 DTLS [RFC9147]とともに使用する場合は、 [RFC9147]の第 5.9節で定義されるバージョンを使用することを意味する。

注: 一般的なハッシュ関数では、12文字を超えるラベルは、 計算のためにハッシュ関数の追加反復を必要とする。 本仕様のラベルはすべて、この制限内に収まるよう選択されている。

鍵は、HKDF-Extract関数およびDerive-Secret関数を使用して、 2つの入力秘密から導出される。 新しい秘密を追加する一般的なパターンは、 現在の秘密状態をSaltとし、 追加する新しい秘密を入力鍵素材(IKM)として HKDF-Extractを使用することである。 このバージョンのTLS 1.3では、2つの入力秘密は次のとおりである。

  • PSK (外部で確立された事前共有鍵、または以前の接続の resumption_secret値から導出された鍵)

  • 非対称鍵確立によって得られる非対称共有秘密 (第7.4節を参照)

これにより、下図 (図5)に示す鍵スケジュールが生成される。 この図では、次の書式規則を使用する。

  • HKDF-Extractは、上からSalt引数を、 左からIKM引数を受け取り、 出力を下に、出力名を右に示す。

  • Derive-SecretのSecret引数は、 入力矢印によって示される。 例えば、Early Secretは、 client_early_traffic_secretを生成するためのSecretである。

  • 「0」は、0に設定されたHash.lengthバイトの文字列を示す。

注: 鍵導出ラベルは、値が「main」秘密と呼ばれているにもかかわらず、 文字列「master」を使用する。 この不一致は、互換性を維持しながら値の名称を変更した結果である。

注: これは、個別のAEAD鍵およびIV鍵など、 すべての末端鍵を示すものではなく、 ハンドシェイクから導出される最初の秘密群を示している。

                 0
                 |
                 v
     PSK -->  HKDF-Extract = Early Secret
                 |
                 +-----> Derive-Secret(.,
                 |                     "ext binder" |
                 |                     "res binder",
                 |                     "")
                 |              = binder_key
                 |
                 +-----> Derive-Secret(., "c e traffic",
                 |                     ClientHello)
                 |              = client_early_traffic_secret
                 |
                 +-----> Derive-Secret(., "e exp master",
                 |                     ClientHello)
                 |              = early_exporter_secret
                 v
            Derive-Secret(., "derived", "")
                 |
  asymmetric     v
   shared --> HKDF-Extract = Handshake Secret
   secret        |
                 +-----> Derive-Secret(., "c hs traffic",
                 |                     ClientHello...ServerHello)
                 |              = client_handshake_traffic_secret
                 |
                 +-----> Derive-Secret(., "s hs traffic",
                 |                     ClientHello...ServerHello)
                 |              = server_handshake_traffic_secret
                 v
            Derive-Secret(., "derived", "")
                 |
                 v
        0 --> HKDF-Extract = Main Secret
                 |
                 +-----> Derive-Secret(., "c ap traffic",
                 |                     ClientHello...server Finished)
                 |              = client_application_traffic_secret_0
                 |
                 +-----> Derive-Secret(., "s ap traffic",
                 |                     ClientHello...server Finished)
                 |              = server_application_traffic_secret_0
                 |
                 +-----> Derive-Secret(., "exp master",
                 |                     ClientHello...server Finished)
                 |              = exporter_secret
                 |
                 +-----> Derive-Secret(., "res master",
                                       ClientHello...client Finished)
                                = resumption_secret
図5: TLS 1.3のメイン鍵スケジュール

ここでの一般的なパターンは、 図の左側に示される秘密はコンテキストを持たない生のエントロピーだけであるのに対し、 右側に示される秘密はハンドシェイクコンテキストを含むため、 追加のコンテキストなしで実際に使用する鍵を導出できるというものである。 同じ秘密であっても、 Derive-Secretの異なる呼び出しは異なるMessages引数を取る場合があることに注意されたい。 0-RTT交換では、Derive-Secretは4つの異なるトランスクリプトで呼び出される。 1-RTTだけの交換では、3つの異なるトランスクリプトで呼び出される。

指定された秘密が利用できない場合、 0に設定されたHash.lengthバイトの文字列からなる0値を使用する。 これはラウンドを省略することを意味しないことに注意されたい。 したがって、PSKを使用しない場合でも、 Early SecretはHKDF-Extract(0, 0)となる。 binder_keyの計算では、外部PSK (TLSの外部でプロビジョニングされたもの)にはラベル「ext binder」を、 再開PSK (以前のハンドシェイクの再開秘密としてプロビジョニングされたもの)には 「res binder」を使用する。 異なるラベルにより、ある種類のPSKを別の種類のPSKに置き換えることを防止する。

サーバーが最終的に選択するPSKに応じて、 複数の潜在的なEarly Secret値が存在する。 クライアントは、潜在的な各PSKについて1つずつ計算する必要がある。 PSKが選択されなかった場合は、 0のPSKに対応するEarly Secretを計算する必要がある。

指定された秘密から導出するすべての値を計算した後、 その秘密は消去することが望ましい

7.2. トラフィック秘密の更新

ハンドシェイクの完了後、 いずれの側も、第4.7.3節で定義される KeyUpdateハンドシェイクメッセージを使用して、 送信用トラフィック鍵を更新できる。 次世代のトラフィック鍵は、 本節で説明するように、 client_/server_application_traffic_secret_Nから client_/server_application_traffic_secret_N+1を生成し、 その後、第7.3節で説明するように トラフィック鍵を再導出することで計算される。

次世代のapplication_traffic_secretは、次のように計算される。

    application_traffic_secret_N+1 =
        HKDF-Expand-Label(application_traffic_secret_N,
                          "traffic upd", "", Hash.length)

client_/server_application_traffic_secret_N+1および それに関連付けられたトラフィック鍵を計算した後、 実装はclient_/server_application_traffic_secret_Nおよび それに関連付けられたトラフィック鍵を削除することが 望ましい

7.3. トラフィック鍵の計算

トラフィック鍵素材は、次の入力値から生成される。

  • 秘密値

  • 生成される特定の値を示す目的値

  • 生成される鍵の長さ

トラフィック鍵素材は、入力トラフィック秘密値から 次を使用して生成される。

[sender]_write_key = HKDF-Expand-Label(Secret, "key", "", key_length)
[sender]_write_iv  = HKDF-Expand-Label(Secret, "iv", "", iv_length)

[sender]は送信側を示す。 各データカテゴリのSecret値を次の表に示す。

表3: トラフィック鍵の秘密
データの種類 秘密
0-RTT ApplicationおよびEndOfEarlyData client_early_traffic_secret
最初のハンドシェイク [sender]_handshake_traffic_secret
ハンドシェイク後およびApplication Data [sender]_application_traffic_secret_N

アラートは、その時点の送信鍵 (そのような鍵が確立されていない場合は平文)で送信される。 基礎となるSecretが変更されるたびに (例えば、ハンドシェイク鍵からApplication Data鍵へ変更するとき、 または鍵更新時)、 すべてのトラフィック鍵素材が再計算される。

7.4. 非対称共有秘密の計算

7.4.1. 有限体 Diffie-Hellman

有限体グループでは、従来のDiffie-Hellman [KEYAGREEMENT]計算を実行する。 ネゴシエートされた鍵(Z)は、ビッグエンディアン形式で符号化し、 素数のサイズになるまで左側を0でパディングすることで、 バイト文字列に変換される。 このバイト文字列は、上記で規定したように、 鍵スケジュールの共有秘密として使用される。

この構成は、先頭の0を削除する以前のバージョンのTLSとは 異なることに注意されたい。

7.4.2. 楕円曲線 Diffie-Hellman

secp256r1、secp384r1、およびsecp521r1では、 ECDH計算 (鍵生成および共有秘密計算を含む)は、 楕円曲線暗号コファクターDiffie-Hellmanプリミティブを使用し、 [KEYAGREEMENT]の第5.6.1.2節および第5.7.1.2節に従って実行される。 共有秘密Zは、ECDH共有秘密の楕円曲線点のx座標を オクテット文字列として表したものである。 [KEYAGREEMENT]の付録C.2で規定される Field-Element-to-Byte String Conversionの出力である オクテット文字列Zは、指定された体について一定の長さを持つことに注意されたい。 このオクテット文字列内の先頭の0は 切り詰めてはならない。 公開鍵の検証要件については、 第4.3.8.2節を参照されたい。

X25519およびX448では、ECDH計算は次のとおりである。

  • KeyShareEntry.key_exchange構造体に入れる公開鍵は、 適切な長さの秘密鍵をスカラー入力として、 標準の公開ベースポイントをu座標点入力として、 ECDHスカラー乗算関数を適用した結果である。

  • ECDH共有秘密は、 秘密鍵をスカラー入力として、 ピアの公開鍵をu座標点入力として、 ECDHスカラー乗算関数を適用した結果である。 出力は処理せず、そのまま使用する。

これらの曲線では、実装は、 Diffie-Hellman共有秘密を計算するために [RFC7748]で規定される方法を 使用することが望ましい。 実装は、計算されたDiffie-Hellman共有秘密が すべて0の値であるかどうかを確認しなければならず、 その場合は、[RFC7748]の第6節で説明されるように、 中止しなければならない。 実装者がこれらの楕円曲線の代替実装を使用する場合、 [RFC7748]の第7節で規定される 追加の確認を実行することが望ましい

7.5. エクスポーター

[RFC5705]は、 TLS疑似乱数関数(PRF)を使用して、 TLSの鍵素材エクスポーターを定義している。 本文書はPRFをHKDFに置き換えるため、 新しい構成が必要になる。エクスポーターインターフェイスは変わらない。

エクスポーター値は次のように計算される。

TLS-Exporter(label, context_value, key_length) =
    HKDF-Expand-Label(Derive-Secret(Secret, label, ""),
                      "exporter", Hash(context_value), key_length)

ここで、Secretはearly_exporter_secretまたは exporter_secretのいずれかである。 アプリケーションによって明示的に指定されない限り、 実装はexporter_secretを使用しなければならない。 early_exporter_secretは、 0-RTTデータでエクスポーターが必要な場合に使用するために定義される。 早期エクスポーターには個別のインターフェイスを使用することが 推奨される。 これにより、エクスポーターの利用者が、 通常のエクスポーターを意図しているときに誤って早期エクスポーターを使用したり、 その逆を行ったりすることを回避できる。

コンテキストが提供されない場合、 context_valueは長さ0である。 したがって、コンテキストを提供しない場合と、 空のコンテキストを提供する場合は同じ値を計算する。 これは、空のコンテキストが、 コンテキストが存在しない場合とは異なる出力を生成していた 以前のバージョンのTLSからの変更である。 本文書の公開時点で、割り当て済みのエクスポーターラベルが、 コンテキストありとなしの両方で使用されることはない。 将来の仕様は、同じラベルについて、 空のコンテキストとコンテキストなしの両方を許可する エクスポーターの使用を定義してはならない。 エクスポーターの新しい使用では、 値が空である場合でも、 すべてのエクスポーター計算でコンテキストを提供することが 望ましい

エクスポーターラベルの形式に関する要件は、 [RFC5705]の第4節で定義される。

8. 0-RTTおよびリプレイ対策

第2.3節および付録F.5で述べたように、 TLSは0-RTTデータに固有のリプレイ保護を提供しない。 懸念すべき潜在的な脅威は2つある。

第1の種類の攻撃は、 0-RTTデータが最大1回だけ受け入れられることを保証するために 状態を共有することで防止できる。 サーバーは、本節で説明する方法のいずれか、または同等の手段を実装することにより、 そのレベルのリプレイ安全性を提供することが 望ましい。 ただし、運用上の懸念により、 すべての配置がそのレベルで状態を維持するわけではないことが理解されている。 したがって、通常動作では、 クライアントはサーバーがこれらの機構のどれを実際に実装しているかを認識できない。 そのため、クライアントはリプレイされても安全であると判断した 早期データだけを送信しなければならない

リプレイの直接的な影響に加えて、 通常は冪等と見なされる操作であっても、 大量のリプレイによって悪用される可能性がある種類の攻撃が存在する (タイミング攻撃、リソース制限の枯渇など。 付録F.5で説明する)。 これらは、各0-RTTペイロードが限られた回数だけリプレイできることを 保証することで軽減できる。 サーバーは、その任意のインスタンス (マシン、スレッド、または関連するサービス提供インフラストラクチャ内のその他のエンティティ)が、 同じ0-RTTハンドシェイクについて0-RTTを最大1回だけ受け入れることを 保証しなければならない。 これにより、リプレイ回数は配置内のサーバーインスタンス数に制限される。 この保証は、最近受信したClientHelloのデータをローカルに記録し、 重複を拒否することや、 同等以上の保証を提供するその他の方法によって実現できる。 「サーバーインスタンスごとに最大1回」という保証は最低要件である。 サーバーは、可能な場合、0-RTTのリプレイをさらに制限することが 望ましい

第2の種類の攻撃はTLS層では防止できず、 すべてのアプリケーションによって 対処しなければならない (例えば、0-RTTデータとともにHTTPを使用する際の指針を提供する [RFC8470]を参照)。 クライアントが何らかの再試行動作を実装するアプリケーションは、 異なるTLS接続上に到着する重複したアプリケーション層要求を 適切に処理することを含め、 何らかのリプレイ対策をすでに実装する必要があることに注意されたい。

8.1. 使い捨てチケット

最も単純なリプレイ対策は、 サーバーが各セッションチケットを1回だけ使用できるようにすることである。 例えば、サーバーは、 未使用の有効なすべてのチケットのデータベースを維持し、 使用された各チケットをデータベースから削除できる。 未知のチケットが提供された場合、 サーバーは完全なハンドシェイクにフォールバックする。

チケットが自己完結型ではなくデータベース鍵であり、 対応するPSKが使用時に削除される場合、 PSKを使用して確立された接続は、 リプレイ対策だけでなく、 データベース項目からPSKのすべての複製が削除された後の前方秘匿性も得られる。 この機構は、非対称鍵交換なしでPSKを使用する場合の PSK使用のセキュリティも向上させる。

この機構では、複数の分散サーバーを持つ環境で、 サーバーノード間でセッションデータベースを共有する必要があるため、 自己暗号化チケットと比較して、 PSK 0-RTT接続の成功率を高く保つことが難しい場合がある。 セッションデータベースとは異なり、 セッションチケットは一貫したストレージがなくても、 PSKベースのセッション確立を正常に実行できる。 ただし、0-RTTを許可する場合、 次の節で詳述するように、 0-RTTデータのリプレイ対策には一貫したストレージが必要である。

8.2. Client Helloの記録

別のリプレイ対策は、 ClientHelloから導出される一意の値 (通常はrandom値またはPSKバインダー)を記録し、 重複を拒否することである。 すべてのClientHelloを記録すると状態が無制限に増加するが、 サーバーは代わりに、指定された時間枠内のClientHelloを記録し、 「obfuscated_ticket_age」を使用して、 その時間枠外でチケットが再利用されないことを保証できる。

これを実装するため、ClientHelloを受信したとき、 サーバーは最初に、 第4.3.11節で説明されているように、 PSKバインダーを検証する。 次に、次節で説明するexpected_arrival_timeを計算し、 記録時間枠外である場合は0-RTTを拒否して、 1-RTTハンドシェイクにフォールバックする。

expected_arrival_timeが時間枠内にある場合、 サーバーは一致するClientHelloを記録済みかどうか確認する。 見つかった場合、サーバーは、 「illegal_parameter」アラートによってハンドシェイクを中止するか、 PSKを受け入れるが0-RTTを拒否する。 一致するClientHelloが見つからなかった場合、 0-RTTを受け入れ、 expected_arrival_timeが時間枠内にある間、 ClientHelloを保存する。 サーバーは、Bloomフィルターなど、 偽陽性を持つデータストアも 実装してもよい。 その場合、見かけ上のリプレイに対して0-RTTを拒否することで 応答しなければならないが、 ハンドシェイクを中止してはならない

サーバーは、ClientHelloの検証済み部分だけから ストレージ鍵を導出しなければならない。 ClientHelloに複数のPSK識別情報が含まれている場合、 サーバーが優先度の低い識別情報を検証しないことを前提として (第4.3.11節で推奨)、 攻撃者はその識別情報に対して異なるバインダー値を持つ 複数のClientHelloを作成できる。 すなわち、クライアントがPSK AおよびBを送信し、 サーバーがAを優先する場合、 攻撃者はAのバインダーに影響を与えずに Bのバインダーを変更できる。 Bのバインダーがストレージ鍵の一部である場合、 このClientHelloは重複として認識されず、 ClientHelloが受け入れられる。 また、0-RTTデータは異なる鍵を使用するため復号できないが、 リプレイキャッシュの汚染などの副作用を引き起こす可能性がある。 検証済みのバインダーまたはClientHello.randomを ストレージ鍵として使用する場合、この攻撃は不可能である。

この機構では、すべての未使用チケットを保存する必要がないため、 再開および0-RTTの割合が高い分散システムで実装しやすい場合がある。 ただし、受信したClientHelloメッセージを確実に保存および取得することが難しいため、 リプレイ対策が弱くなる可能性がある。 このような多くのシステムでは、 受信したすべてのClientHelloについて、 グローバルに一貫したストレージを持つことは現実的ではない。 この場合、指定されたチケットについて、 単一のストレージゾーンだけを権威あるものとし、 その他のゾーンではそのチケットの0-RTTを拒否することで、 最も強いリプレイ対策を提供できる。 この方法では、1つのゾーンだけが0-RTTデータを受け入れるため、 攻撃者による単純なリプレイを防止できる。 より弱い設計は、各ゾーンに個別のストレージを実装し、 どのゾーンでも0-RTTを許可することである。 この方法では、リプレイ回数がゾーンごとに1回に制限される。 いずれの設計でも、 アプリケーションメッセージの重複は当然ながら引き続き発生し得る。

実装を新たに起動した場合、 記録時間枠のいずれかの部分が起動時刻と重なる間は、 0-RTTを拒否することが望ましい。 そうでない場合、その期間中に最初に送信されたリプレイを 受け入れる危険がある。

注: クライアントの時計がサーバーの時計より大幅に速く進んでいる場合、 将来の時間枠外にあるClientHelloを受信する可能性がある。 この場合、1-RTTでは受け入れられ、 クライアントの再試行を引き起こし、 後で0-RTTとして受け入れ可能になる場合がある。 これは、第 8節で説明した第2の種類の攻撃の別の変種である。

8.3. 鮮度チェック

ClientHelloはクライアントが送信した時刻を示すため、 ClientHelloが合理的に最近送信された可能性が高いかどうかを 効率的に判定し、そのようなClientHelloだけについて0-RTTを受け入れ、 それ以外の場合は1-RTTハンドシェイクにフォールバックできる。 これは、第8.2節で説明する ClientHelloストレージ機構に必要である。 そうでなければ、サーバーは無制限の数のClientHelloを保存する必要があるためである。 また、0-RTTに使用できないClientHelloを効率的に拒否できるため、 自己完結型の使い捨てチケットにも有用な最適化である。

この機構を実装するため、サーバーは、 サーバーがセッションチケットを生成した時刻に、 クライアントとサーバー間の往復時間の推定値を加えた値を保存する必要がある。 すなわち、

    adjusted_creation_time = creation_time + estimated_RTT

この値はチケットに符号化できるため、 未使用の各チケットについて状態を保持する必要がなくなる。 サーバーは、クライアントの「pre_shared_key」拡張内の 「obfuscated_ticket_age」パラメーターから、 チケットの「ticket_age_add」値を減算することで、 クライアントから見たチケットの経過時間を判定できる。 サーバーは、ClientHelloのexpected_arrival_timeを 次のように判定できる。

  expected_arrival_time = adjusted_creation_time + clients_ticket_age

新しいClientHelloを受信すると、 expected_arrival_timeを現在のサーバーの壁時計時刻と比較し、 一定量を超えて異なる場合は0-RTTを拒否する。 ただし、1-RTTハンドシェイクの完了は許可できる。

expected_arrival_timeと測定時刻の不一致を引き起こす 潜在的な誤差源がいくつか存在する。 クライアントとサーバーの時計の進み方の差は、 絶対時刻が大きくずれる可能性はあるものの、 最小限である可能性が高い。 ネットワーク伝播遅延が、 正当な経過時間の値に不一致を生じさせる最も可能性の高い原因である。 NewSessionTicketメッセージおよびClientHelloメッセージは、 再送信されて遅延する場合があり、 その遅延はTCPによって隠される可能性がある。 インターネット上のクライアントでは、 時計の誤差および測定値の変動を考慮するため、 約10秒の時間枠が必要になることを意味する。 その他の配置シナリオでは、異なる要件を持つ場合がある。 時計のずれの分布は対称ではないため、 最適なトレードオフには、 許容される不一致値の非対称な範囲が含まれる場合がある。

鮮度チェックだけでは、 誤差時間枠内のリプレイを検出しないため、 リプレイの防止には不十分であることに注意されたい。 この時間枠には、帯域幅およびシステム容量によっては、 実環境で数十億回のリプレイが含まれる可能性がある。 さらに、この鮮度チェックはClientHelloを受信した時点でだけ行われ、 後続の早期Application Dataレコードを受信した時点では行われない。 早期データを受け入れた後も、 レコードはより長い期間にわたってサーバーへストリーミングされ続ける場合がある。

9. 適合要件

9.1. 実装必須の 暗号スイート

別段の規定を行うアプリケーションプロファイル標準がない場合、

  • TLS適合アプリケーションは、 TLS_AES_128_GCM_SHA256 [GCM]暗号スイートを 実装しなければならず、 TLS_AES_256_GCM_SHA384 [GCM]および TLS_CHACHA20_POLY1305_SHA256 [RFC8439]暗号スイートを 実装することが望ましい付録B.4を参照)。

  • TLS適合アプリケーションは、 rsa_pkcs1_sha256 (証明書用)、rsa_pss_rsae_sha256 (CertificateVerifyおよび証明書用)、および ecdsa_secp256r1_sha256によるデジタル署名を サポートしなければならない。 TLS適合アプリケーションは、secp256r1 (NIST P-256)による鍵交換を サポートしなければならず、 X25519 [RFC7748]による鍵交換を サポートすることが望ましい

9.2. 実装必須の 拡張

別段の規定を行うアプリケーションプロファイル標準がない場合、 TLS適合アプリケーションは、次のTLS拡張を 実装しなければならない

  • サポートされるバージョン (「supported_versions」、第4.3.1節

  • Cookie (「cookie」、第4.3.2節

  • 署名アルゴリズム (「signature_algorithms」、第4.3.3節

  • 証明書用署名アルゴリズム (「signature_algorithms_cert」、第4.3.3節

  • サポートされるグループ (「supported_groups」、第4.3.7節

  • 鍵共有 (「key_share」、第4.3.8節

  • サーバー名指示 (「server_name」、[RFC6066]の第3節

すべての実装は、適用可能な機能を提示するとき、 次の拡張を送信し、使用 しなければならない

  • 「supported_versions」は、 すべてのClientHello、ServerHello、およびHelloRetryRequestメッセージで 必須である

  • 「signature_algorithms」は、 証明書認証で必須である

  • 「supported_groups」は、 DHEまたはECDHE鍵交換を使用するClientHelloメッセージで 必須である

  • 「key_share」は、 DHEまたはECDHE鍵交換で 必須である

  • 「pre_shared_key」は、 PSK鍵合意で必須である

  • 「psk_key_exchange_modes」は、 PSK鍵合意で必須である

ClientHelloの本体に0x0304を含む 「supported_versions」拡張がある場合、 クライアントは本仕様を使用してネゴシエートしようとしていると見なされる。 このようなClientHelloメッセージは、 次の要件を満たさなければならない

  • 「pre_shared_key」拡張を含まない場合、 「signature_algorithms」拡張と 「supported_groups」拡張の両方を 含まなければならない

  • 「supported_groups」拡張を含む場合、 「key_share」拡張も 含まなければならず、 その逆も同様である。 空のKeyShare.client_shares一覧は許可される。

これらの要件に適合しないClientHelloを受信したサーバーは、 「missing_extension」アラートによってハンドシェイクを 中止しなければならない

さらに、すべての実装は、 「server_name」拡張を使用できるアプリケーションで、 この拡張の使用をサポートしなければならない。 サーバーは、クライアントに有効な「server_name」拡張の送信を 要求してもよい。 この拡張を要求するサーバーは、 「server_name」拡張のないClientHelloに対し、 「missing_extension」アラートによって接続を終了して 応答することが望ましい

9.3. プロトコル不変条件

本節では、TLSエンドポイントおよびミドルボックスが 従わなければならない不変条件を説明する。 これは以前のバージョンのTLSにも適用される。

TLSは、安全かつ互換性を保って拡張できるよう設計されている。 新しいクライアントまたはサーバーは、新しいピアと通信する場合、 共通する最も優先度の高いパラメーターをネゴシエートすべきである。 TLSハンドシェイクはダウングレード保護を提供する。 TLSを終了せずに新しいクライアントと新しいサーバーの間でトラフィックを転送する ミドルボックスは、ハンドシェイクに影響を与えられないはずである (付録F.1を参照)。 同時に、配置は異なる速度で更新されるため、 新しいクライアントまたはサーバーは、 古いエンドポイントと相互運用できるようにするため、 古いパラメーターのサポートを継続 してもよい

これを機能させるため、実装は拡張可能なフィールドを 正しく処理しなければならない

  • ClientHelloを送信するクライアントは、 そこで広告するGREASE以外のすべての [RFC8701]パラメーターを サポートしなければならない。 そうでない場合、サーバーがそれらのパラメーターの1つを選択することで、 相互運用に失敗する可能性がある。

  • ClientHelloを受信したサーバーは、 認識できないすべての暗号スイート、拡張、およびその他のパラメーターを 正しく無視しなければならない。 そうでない場合、新しいクライアントとの相互運用に失敗する可能性がある。 TLS 1.3では、CertificateRequestまたはNewSessionTicketを受信したクライアントも、 認識できないすべての拡張を 無視しなければならない

  • TLS接続を終了するミドルボックスは、 元のクライアントに対して適合するTLSサーバーとして 動作しなければならない。 これには、クライアントが受け入れる証明書を持つことが含まれる。 また、元のサーバーに対して適合するTLSクライアントとしても 動作しなければならない。 これには、元のサーバーの証明書を検証することが含まれる。 特に、理解できるパラメーターだけを含む独自のClientHelloを 生成しなければならず、 エンドポイントの値を転送するのではなく、 新しいServerHelloのrandom値を 生成しなければならない

    TLSのプロトコル要件およびセキュリティ分析は、 2つの接続に個別に適用されるだけであることに注意されたい。 TLS終端装置を安全に配置するには、 本文書の範囲外である追加のセキュリティ上の考慮事項が必要である。

  • 理解できないClientHelloパラメーターを転送するミドルボックスは、 そのClientHello以降のメッセージを 処理してはならない。 後続するすべてのトラフィックを変更せずに 転送しなければならない。 そうでない場合、新しいクライアントおよびサーバーとの 相互運用に失敗する可能性がある。

    転送されたClientHelloには、 ミドルボックスがサポートしない機能の広告が含まれる場合があるため、 応答にはミドルボックスが認識できない将来のTLS追加機能が含まれる可能性がある。 これらの追加機能は、ClientHello以降の任意のメッセージを 自由に変更してもよい。 特に、ServerHelloで送信される値、 ServerHelloの形式、およびTLSCiphertextの形式が 変更される場合がある。

TLS 1.3の設計は、 広く配置された不適合なTLSミドルボックスによって制約された (付録E.4を参照)。 ただし、不変条件を緩和するものではない。 これらのミドルボックスは引き続き不適合である。

10. セキュリティに関する考慮事項

セキュリティ上の問題は、本文書全体、特に 付録C付録E、および付録Fで論じられている。

11. IANAに関する考慮事項

本文書は、当初 [RFC4346]で作成され、[RFC8446]および[RFC8447]で更新された複数のレジストリを使用する。[RFC8446][RFC8447]、および本文書の間の変更は、第11.1節で説明する。 IANAは、これらのRFCへの参照を本文書への参照に置き換えた。レジストリおよびその 割り当てポリシーは次のとおりである。

本文書は、当初 [RFC4366]で作成されたTLS ExtensionType Valuesレジストリも使用する。IANAは、 本文書を参照するよう更新した。レジストリへの変更は次のとおりである。

本文書は、当初[RFC6091]で作成され、 [RFC8447]で更新されたTLS Certificate Typesレジストリの 2つの項目を更新する。IANAは、値1の項目を、名称「OpenPGP_RESERVED」、 「Recommended」値「N」、およびコメント「TLS 1.3より前のTLSバージョンで使用された。」を持つように更新した。 IANAは、値0の項目を、名称 「X509」、「Recommended」値「Y」、およびコメント「TLS 1.3より前はX.509であった」を持つように更新した。

本文書は、当初[RFC6961]で作成された TLS Certificate Status Typesレジストリの項目を更新する。IANAは、 値2の項目を、名称「ocsp_multi_RESERVED」およびコメント「TLS 1.3より前のTLSバージョンで 使用された」を持つように更新した。

本文書は、TLS Supported Groups レジストリの2つの項目を更新する ([RFC4492]によって別の名称で作成され、現在は [RFC8422]によって維持され、[RFC7919]および[RFC8447]によって更新されている)。 値29および30(x25519およびx448)の項目は、 本文書も参照するよう更新された。

さらに、本文書は、IANAによって維持される 2つの新しいレジストリを定義する。

TLS ExtensionType Values、TLS Cipher Suites、TLS Supported Groups、TLS Exporter Labels、TLS HashAlgorithm、TLS Certificate Types、 TLSPskKeyExchangeMode、およびTLS SignatureSchemeレジストリには、 「Recommended」列がある。「Recommended」列の値および設定に関する 追加情報については、[RFC9847]の第3節を参照されたい。

11.1. このRFCにおける変更

IANAは、IANAレジストリ内の[RFC8446]へのすべての参照を、 本文書への参照に更新した。

IANAは、TLS SignatureSchemeおよび PskKeyExchangeModeレジストリの「Recommended」列の手順を、 [RFC9847]に一致するよう更新した。

IANAは、TLS ExtensionType Valuesレジストリ内の 「extended_master_secret」値を「extended_main_secret」に改名した。

IANAは、TLS Alertsレジストリに、 第6節で示された値を持つ 「general_error」アラートの値を作成した。

IANAは、TLS ExtensionType Valuesレジストリ内の status_requestおよびsupported_groups項目に、 本文書への参照を追加した。

IANAは、cached_infoについて、 「TLS 1.3」列内のTLS ExtensionType値を「CH, EE」に更新した。

12. 参考文献

12.1. 規範的参考文献

[GCM]
Dworkin, M., 「ブロック暗号 動作モードに関する勧告: Galois/Counter Mode(GCM)およびGMAC」, NIST SP 800-38D, DOI 10.6028/NIST.SP.800-38D, , <https://doi.org/10.6028/NIST.SP.800-38D>.
[KEYAGREEMENT]
Barker, E., Chen, L., Roginsky, A., Vassilev, A., and R. Davis, 「離散対数暗号を使用する ペアワイズ鍵確立方式に関する勧告」, 米国国立標準技術研究所, DOI 10.6028/nist.sp.800-56ar3, , <https://doi.org/10.6028/nist.sp.800-56ar3>.
[RFC2104]
Krawczyk, H., Bellare, M., and R. Canetti, 「HMAC: メッセージ認証のための 鍵付きハッシュ」, RFC 2104, DOI 10.17487/RFC2104, , <https://www.rfc-editor.org/info/rfc2104>.
[RFC2119]
Bradner, S., 「要件レベルを示すために RFCで使用するキーワード」, BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/info/rfc2119>.
[RFC3279]
Bassham, L., Polk, W., and R. Housley, 「インターネットX.509公開鍵基盤の 証明書および証明書失効リスト(CRL)プロファイル用アルゴリズムおよび識別子」, RFC 3279, DOI 10.17487/RFC3279, , <https://www.rfc-editor.org/info/rfc3279>.
[RFC5116]
McGrew, D., 「認証暗号のインターフェイスおよび アルゴリズム」, RFC 5116, DOI 10.17487/RFC5116, , <https://www.rfc-editor.org/info/rfc5116>.
[RFC5280]
Cooper, D., Santesson, S., Farrell, S., Boeyen, S., Housley, R., and W. Polk, 「インターネットX.509公開鍵基盤の証明書および証明書 失効リスト(CRL)プロファイル」, RFC 5280, DOI 10.17487/RFC5280, , <https://www.rfc-editor.org/info/rfc5280>.
[RFC5705]
Rescorla, E., 「トランスポート層セキュリティ (TLS)の鍵素材エクスポーター」, RFC 5705, DOI 10.17487/RFC5705, , <https://www.rfc-editor.org/info/rfc5705>.
[RFC5756]
Turner, S., Brown, D., Yiu, K., Housley, R., and T. Polk, 「RSAES-OAEPおよび RSASSA-PSSアルゴリズムパラメーターの更新」, RFC 5756, DOI 10.17487/RFC5756, , <https://www.rfc-editor.org/info/rfc5756>.
[RFC5869]
Krawczyk, H. and P. Eronen, 「HMACベースのExtract-and-Expand鍵導出関数 (HKDF)」, RFC 5869, DOI 10.17487/RFC5869, , <https://www.rfc-editor.org/info/rfc5869>.
[RFC6066]
Eastlake 3rd, D., 「トランスポート層 セキュリティ(TLS)拡張: 拡張の定義」, RFC 6066, DOI 10.17487/RFC6066, , <https://www.rfc-editor.org/info/rfc6066>.
[RFC6655]
McGrew, D. and D. Bailey, 「トランスポート層セキュリティ(TLS)用AES-CCM暗号スイート」, RFC 6655, DOI 10.17487/RFC6655, , <https://www.rfc-editor.org/info/rfc6655>.
[RFC6960]
Santesson, S., Myers, M., Ankney, R., Malpani, A., Galperin, S., and C. Adams, 「X.509インターネット公開鍵基盤オンライン証明書状態 プロトコル - OCSP」, RFC 6960, DOI 10.17487/RFC6960, , <https://www.rfc-editor.org/info/rfc6960>.
[RFC6961]
Pettersen, Y., 「トランスポート層 セキュリティ(TLS)の複数証明書状態要求拡張」, RFC 6961, DOI 10.17487/RFC6961, , <https://www.rfc-editor.org/info/rfc6961>.
[RFC6962]
Laurie, B., Langley, A., and E. Kasper, 「証明書 透明性」, RFC 6962, DOI 10.17487/RFC6962, , <https://www.rfc-editor.org/info/rfc6962>.
[RFC6979]
Pornin, T., 「デジタル署名アルゴリズム (DSA)および楕円曲線デジタル署名アルゴリズム (ECDSA)の決定論的使用」, RFC 6979, DOI 10.17487/RFC6979, , <https://www.rfc-editor.org/info/rfc6979>.
[RFC7301]
Friedl, S., Popov, A., Langley, A., and E. Stephan, 「トランスポート層セキュリティ(TLS)のアプリケーション層プロトコル ネゴシエーション拡張」, RFC 7301, DOI 10.17487/RFC7301, , <https://www.rfc-editor.org/info/rfc7301>.
[RFC7507]
Moeller, B. and A. Langley, 「プロトコルダウングレード攻撃を防止するための TLSフォールバック通知暗号スイート値(SCSV)」, RFC 7507, DOI 10.17487/RFC7507, , <https://www.rfc-editor.org/info/rfc7507>.
[RFC7627]
Bhargavan, K., Ed., Delignat-Lavaud, A., Pironti, A., Langley, A., and M. Ray, 「トランスポート 層セキュリティ(TLS)のセッションハッシュおよび拡張マスターシークレット拡張」, RFC 7627, DOI 10.17487/RFC7627, , <https://www.rfc-editor.org/info/rfc7627>.
[RFC7748]
Langley, A., Hamburg, M., and S. Turner, 「セキュリティ用 楕円曲線」, RFC 7748, DOI 10.17487/RFC7748, , <https://www.rfc-editor.org/info/rfc7748>.
[RFC7919]
Gillmor, D., 「トランスポート層セキュリティ (TLS)用のネゴシエートされた有限体一時Diffie-Hellmanパラメーター」, RFC 7919, DOI 10.17487/RFC7919, , <https://www.rfc-editor.org/info/rfc7919>.
[RFC8017]
Moriarty, K., Ed., Kaliski, B., Jonsson, J., and A. Rusch, 「PKCS #1: RSA暗号仕様バージョン 2.2」, RFC 8017, DOI 10.17487/RFC8017, , <https://www.rfc-editor.org/info/rfc8017>.
[RFC8032]
Josefsson, S. and I. Liusvaara, 「Edwards曲線デジタル署名アルゴリズム (EdDSA)」, RFC 8032, DOI 10.17487/RFC8032, , <https://www.rfc-editor.org/info/rfc8032>.
[RFC8126]
Cotton, M., Leiba, B., and T. Narten, 「RFCのIANAに関する考慮事項の 節を記述するための指針」, BCP 26, RFC 8126, DOI 10.17487/RFC8126, , <https://www.rfc-editor.org/info/rfc8126>.
[RFC8174]
Leiba, B., 「RFC 2119のキーワードにおける 大文字と小文字の曖昧さ」, BCP 14, RFC 8174, DOI 10.17487/RFC8174, , <https://www.rfc-editor.org/info/rfc8174>.
[RFC8439]
Nir, Y. and A. Langley, 「IETFプロトコル用のChaCha20およびPoly1305」, RFC 8439, DOI 10.17487/RFC8439, , <https://www.rfc-editor.org/info/rfc8439>.
[RFC8701]
Benjamin, D., 「TLSの拡張性への Generate Random Extensions And Sustain Extensibility(GREASE)の適用」, RFC 8701, DOI 10.17487/RFC8701, , <https://www.rfc-editor.org/info/rfc8701>.
[RFC8996]
Moriarty, K. and S. Farrell, 「TLS 1.0およびTLS 1.1の非推奨化」, BCP 195, RFC 8996, DOI 10.17487/RFC8996, , <https://www.rfc-editor.org/info/rfc8996>.
[SHS]
「セキュアハッシュ標準」, 米国 国立標準技術研究所, DOI 10.6028/nist.fips.180-4, , <https://doi.org/10.6028/nist.fips.180-4>.
[X690]
ITU-T, 「情報技術 - ASN.1 符号化規則: 基本符号化規則(BER)、標準符号化規則 (CER)および識別符号化規則(DER)の仕様」, ITU-T 勧告 X.690, , <https://www.itu.int/rec/T-REC-X.690-202102-I/en>.

12.2. 参考情報としての参考文献

[AEAD-LIMITS]
Luykx, A. and K. Paterson, 「TLSにおける認証暗号使用の制限」, , <https://eprint.iacr.org/2024/051>.
[BBFGKZ16]
Bhargavan, K., Brzuska, C., Fournet, C., Green, M., Kohlweiss, M., and S. Zanella-Beguelin, 「鍵交換プロトコルにおける ダウングレード耐性」, IEEE, 2016 IEEEセキュリティおよびプライバシーシンポジウム(SP)pp. 506-525, DOI 10.1109/sp.2016.37, , <https://doi.org/10.1109/sp.2016.37>.
[BBK17]
Bhargavan, K., Blanchet, B., and N. Kobeissi, 「TLS 1.3標準候補の 検証済みモデルおよび参照実装」, IEEE, 2017 IEEEセキュリティ およびプライバシーシンポジウム(SP)pp. 483-502, DOI 10.1109/sp.2017.26, , <https://doi.org/10.1109/sp.2017.26>.
[BDFKPPRSZZ16]
Bhargavan, K., Delignat-Lavaud, A., Fournet, C., Kohlweiss, M., Pan, J., Protzenko, J., Rastogi, A., Swamy, N., Zanella-Beguelin, S., and J. Zinzindohoue, 「TLS 1.3レコード層の実装および証明」, IEEEセキュリティおよびプライバシーシンポジウム(サンノゼ) 2017予稿集, , <https://eprint.iacr.org/2016/1178>.
[Ben17a]
Benjamin, D., 「IETF 100における TLS WGでの発表」, IETF 100予稿集, , <https://datatracker.ietf.org/meeting/100/materials/slides-100-tls-sessa-tls13/>.
[Ben17b]
Benjamin, D., 「Chromeから得られた TLS 1.3の追加結果」, TLSメーリング リストへのメッセージ, , <https://mailarchive.ietf.org/arch/msg/tls/i9blmvG2BEPf1s1OJkenHknRw9c/>.
[Blei98]
Bleichenbacher, D., 「RSA暗号標準 PKCS #1に基づくプロトコルに対する選択暗号文攻撃」, CRYPTO '98予稿集, , <https://link.springer.com/chapter/10.1007/bfb0055716>.
[BMMRT15]
Badertscher, C., Matt, C., Maurer, U., Rogaway, P., and B. Tackmann, 「拡張セキュア チャネルとTLS 1.3レコード層の目標」, ProvSec 2015, , <https://eprint.iacr.org/2015/394>.
[BT16]
Bellare, M. and B. Tackmann, 「認証暗号のマルチユーザーセキュリティ: TLS 1.3におけるAES-GCM」, CRYPTO 2016予稿集, , <https://eprint.iacr.org/2016/564>.
[CCG16]
Cohn-Gordon, K., Cremers, C., and L. Garratt, 「侵害後 セキュリティについて」, IEEE, 2016 IEEE第29回コンピューターセキュリティ基礎シンポジウム(CSF)pp. 164-178, DOI 10.1109/csf.2016.19, , <https://doi.org/10.1109/csf.2016.19>.
[CHECKOWAY]
Checkoway, S., Maskiewicz, J., Garman, C., Fried, J., Cohney, S., Green, M., Heninger, N., Weinmann, R., Rescorla, E., and H. Shacham, 「Juniper Dual EC事件の体系的分析」, ACM, 2016 ACM SIGSACコンピューターおよび通信セキュリティ会議予稿集 pp. 468-479, DOI 10.1145/2976749.2978395, , <https://doi.org/10.1145/2976749.2978395>.
[CHHSV17]
Cremers, C., Horvat, M., Hoyland, J., van der Merwe, T., and S. Scott, 「扱いにくいハンドシェイク: リビジョン18のハンドシェイク後モードにおけるクライアント認証について、 クライアントとサーバーの見解が不一致となる可能性」, TLSメーリングリストへのメッセージ, , <https://mailarchive.ietf.org/arch/msg/tls/crdSCgiW-94z2joulYJtuA52E9E/>.
[CHSV16]
Cremers, C., Horvat, M., Scott, S., and T. van der Merwe, 「TLS 1.3の自動分析および検証: 0-RTT、再開 および遅延認証」, IEEE, 2016 IEEEセキュリティおよびプライバシーシンポジウム(SP)pp. 470-485, DOI 10.1109/sp.2016.35, , <https://doi.org/10.1109/sp.2016.35>.
[CK01]
Canetti, R. and H. Krawczyk, 「鍵交換プロトコルの分析とセキュア チャネル構築への利用」, Springer Berlin Heidelberg, コンピューターサイエンス講義ノート pp. 453-474, DOI 10.1007/3-540-44987-6_28, ISBN ["9783540420705", "9783540449874"], , <https://doi.org/10.1007/3-540-44987-6_28>.
[CLINIC]
Miller, B., Huang, L., Joseph, A., and J. Tygar, 「あなたが診療所へ行った理由を私は知っている: HTTPS トラフィック分析のリスクと実現」, Springer International Publishing, コンピューターサイエンス講義ノート pp. 143-163, DOI 10.1007/978-3-319-08506-7_8, ISBN ["9783319085050", "9783319085067"], , <https://doi.org/10.1007/978-3-319-08506-7_8>.
[DFGS15]
Dowling, B., Fischlin, M., Guenther, F., and D. Stebila, 「TLS 1.3 draft-10の完全および事前共有 鍵ハンドシェイクプロトコルの暗号学的分析」, ACM CCS 2015予稿集, , <https://eprint.iacr.org/2015/914>.
[DFGS16]
Dowling, B., Fischlin, M., Guenther, F., and D. Stebila, 「TLS 1.3 draft-10の完全および事前共有 鍵ハンドシェイクプロトコルの暗号学的分析」, TRON 2016, , <https://eprint.iacr.org/2016/081>.
[DH76]
Diffie, W. and M. Hellman, 「暗号学の新しい方向性」, 米国電気電子学会(IEEE), IEEE情報理論論文誌 vol. 22, no. 6, pp. 644-654, DOI 10.1109/tit.1976.1055638, , <https://doi.org/10.1109/tit.1976.1055638>.
[DOW92]
Diffie, W., Van Oorschot, P., and M. Wiener, 「認証および 認証付き鍵交換」, Springer Science and Business Media LLC, Designs, Codes and Cryptography vol. 2, no. 2, pp. 107-125, DOI 10.1007/bf00124891, , <https://doi.org/10.1007/bf00124891>.
[DSA-1571-1]
Weimer, F., 「[SECURITY] [DSA 1571-1] 予測可能な乱数生成器を修正する新しいopensslパッケージ」, debian-security-announceメーリングリストへのメッセージ, , <https://www.debian.org/security/2008/dsa-1571>.
[DSS]
「デジタル署名標準(DSS)」, 米国国立標準技術研究所, DOI 10.6028/nist.fips.186-5, , <https://doi.org/10.6028/nist.fips.186-5>.
[ECDP]
Chen, L., Moody, D., Regenscheid, A., Robinson, A., and K. Randall, 「離散対数ベース暗号に関する 勧告: 楕円曲線ドメインパラメーター」, 米国国立標準技術研究所, DOI 10.6028/nist.sp.800-186, , <https://doi.org/10.6028/nist.sp.800-186>.
[FETCH]
WHATWG, 「Fetch」, WHATWG現行標準, <https://fetch.spec.whatwg.org/>. コミットスナップショット: https://fetch.spec.whatwg.org/commit-snapshots/4775fcb48042c8411df497c0b7cf167b4240004f/
[FG17]
Fischlin, M. and F. Guenther, 「ゼロラウンドトリップ時間に対するリプレイ攻撃: TLS 1.3 ハンドシェイク候補の場合」, Euro S&P 2017予稿集, , <https://eprint.iacr.org/2017/082>.
[FGSW16]
Fischlin, M., Guenther, F., Schmidt, B., and B. Warinschi, 「鍵交換における鍵確認: 形式的な取り扱いと TLS 1.3への影響」, IEEEセキュリティ およびプライバシーシンポジウム(Oakland)2016予稿集, DOI 10.1109/SP.2016.34, , <http://ieeexplore.ieee.org/document/7546517/>.
[FW15]
Weimer, F., 「TLS完全前方秘匿性を 使用したRSA鍵の因数分解」, Red Hatブログ, , <https://www.redhat.com/en/blog/factoring-rsa-keys-tls-perfect-forward-secrecy>.
[HCJC16]
Husák, M., Čermák, M., Jirsík, T., and P. Čeleda, 「受動的SSL/TLSフィンガープリンティングを使用したHTTPSトラフィック分析 およびクライアント識別」, Springer Science and Business Media LLC, EURASIP Journal on Information Security vol. 2016, no. 1, DOI 10.1186/s13635-016-0030-7, , <https://doi.org/10.1186/s13635-016-0030-7>.
[HGFS15]
Hlauschek, C., Gruber, M., Fankhauser, F., and C. Schanes, 「パンドラの箱をこじ開ける: TLSに対する KCI攻撃」, USENIX攻撃技術ワークショップ予稿集, , <https://www.usenix.org/conference/woot15/workshop-program/presentation/hlauschek>.
[JSS15]
Jager, T., Schwenk, J., and J. Somorovsky, 「PKCS#1 v1.5暗号化の 弱点に対するTLS 1.3およびQUICのセキュリティ」, ACM, 第22回ACM SIGSACコンピューターおよび通信セキュリティ会議予稿集 pp. 1185-1196, DOI 10.1145/2810103.2813657, , <https://doi.org/10.1145/2810103.2813657>.
[Kraw10]
Krawczyk, H., 「暗号学的 抽出および鍵導出: HKDF方式」, CRYPTO 2010予稿集, , <https://eprint.iacr.org/2010/264>.
[Kraw16]
Krawczyk, H., 「鍵交換のための 一方向認証から相互認証へのコンパイラー(TLS 1.3のクライアント認証への応用を含む」, ACM CCS 2016予稿集, , <https://eprint.iacr.org/2016/711>.
[KW16]
Krawczyk, H. and H. Wee, 「OPTLSプロトコルおよびTLS 1.3」, Euro S&P 2016予稿集, , <https://eprint.iacr.org/2015/978>.
[LXZFH16]
Li, X., Xu, J., Zhang, Z., Feng, D., and H. Hu, 「TLS 1.3候補の複数ハンドシェイク セキュリティ」, IEEE, 2016 IEEEセキュリティおよびプライバシーシンポジウム(SP)pp. 486-505, DOI 10.1109/sp.2016.36, , <https://doi.org/10.1109/sp.2016.36>.
[Mac17]
MacCarthaigh, C., 「TLS 1.3 0-RTTのセキュリティレビュー」, , <https://github.com/tlswg/tls13-spec/issues/1001>.
[MM24]
Moustafa, M., Sethi, M., and T. Aura, 「TLSにおける生の公開鍵の 識別情報への誤結合」, arxiv:2411.09770, , <https://arxiv.org/pdf/2411.09770>.
[PS18]
Patton, C. and T. Shrimpton, 「部分的に規定されたチャネル: 省略のないTLS 1.3レコード層」, , <https://eprint.iacr.org/2018/634>.
[PSK-FINISHED]
Cremers, C., Horvat, M., van der Merwe, T., and S. Scott, 「リビジョン10: PSK中にクライアント認証を許可した場合に 起こり得る攻撃」, TLSメーリングリストへのメッセージ, , <https://mailarchive.ietf.org/arch/msg/tls/TugB5ddJu3nYg7chcyeIyUqWSbA/>.
[REKEY]
Abdalla, M. and M. Bellare, 「鍵の有効期間の延長: 再鍵付け技法の セキュリティに関する比較分析」, Springer Berlin Heidelberg, コンピューターサイエンス講義ノート pp. 546-559, DOI 10.1007/3-540-44448-3_42, ISBN ["9783540414049", "9783540444480"], , <https://doi.org/10.1007/3-540-44448-3_42>.
[Res17a]
Rescorla, E., 「Firefox TLS 1.3 ミドルボックス実験の予備データ」, TLS メーリングリストへのメッセージ, , <https://mailarchive.ietf.org/arch/msg/tls/RBp0X-OWNuWXugFJRV7c_hIU0dI/>.
[Res17b]
Rescorla, E., 「追加の互換性 測定結果」, TLSメーリング リストへのメッセージ, , <https://mailarchive.ietf.org/arch/msg/tls/6pGGT-wm5vSkacMFPEPvFMEnj-M/>.
[RFC2246]
Dierks, T. and C. Allen, 「TLSプロトコル バージョン1.0」, RFC 2246, DOI 10.17487/RFC2246, , <https://www.rfc-editor.org/info/rfc2246>.
[RFC3552]
Rescorla, E. and B. Korver, 「セキュリティに関する考慮事項についてRFC本文を記述するための指針」, BCP 72, RFC 3552, DOI 10.17487/RFC3552, , <https://www.rfc-editor.org/info/rfc3552>.
[RFC4086]
Eastlake 3rd, D., Schiller, J., and S. Crocker, 「セキュリティのための乱数要件」, BCP 106, RFC 4086, DOI 10.17487/RFC4086, , <https://www.rfc-editor.org/info/rfc4086>.
[RFC4346]
Dierks, T. and E. Rescorla, 「トランスポート層セキュリティ(TLS)プロトコル バージョン1.1」, RFC 4346, DOI 10.17487/RFC4346, , <https://www.rfc-editor.org/info/rfc4346>.
[RFC4366]
Blake-Wilson, S., Nystrom, M., Hopwood, D., Mikkelsen, J., and T. Wright, 「トランスポート層 セキュリティ(TLS)拡張」, RFC 4366, DOI 10.17487/RFC4366, , <https://www.rfc-editor.org/info/rfc4366>.
[RFC4492]
Blake-Wilson, S., Bolyard, N., Gupta, V., Hawk, C., and B. Moeller, 「トランスポート層セキュリティ(TLS)用 楕円曲線暗号(ECC)暗号スイート」, RFC 4492, DOI 10.17487/RFC4492, , <https://www.rfc-editor.org/info/rfc4492>.
[RFC5077]
Salowey, J., Zhou, H., Eronen, P., and H. Tschofenig, 「サーバー側状態を使用しないトランスポート層セキュリティ(TLS) セッション再開」, RFC 5077, DOI 10.17487/RFC5077, , <https://www.rfc-editor.org/info/rfc5077>.
[RFC5246]
Dierks, T. and E. Rescorla, 「トランスポート層セキュリティ(TLS)プロトコル バージョン1.2」, RFC 5246, DOI 10.17487/RFC5246, , <https://www.rfc-editor.org/info/rfc5246>.
[RFC5763]
Fischl, J., Tschofenig, H., and E. Rescorla, 「Datagram Transport Layer Security (DTLS)を使用してセキュアリアルタイムトランスポートプロトコル(SRTP)の セキュリティコンテキストを確立するための枠組み」, RFC 5763, DOI 10.17487/RFC5763, , <https://www.rfc-editor.org/info/rfc5763>.
[RFC5764]
McGrew, D. and E. Rescorla, 「セキュアリアルタイムトランスポートプロトコル(SRTP)の鍵を 確立するためのDatagram Transport Layer Security(DTLS)拡張」, RFC 5764, DOI 10.17487/RFC5764, , <https://www.rfc-editor.org/info/rfc5764>.
[RFC5929]
Altman, J., Williams, N., and L. Zhu, 「TLSのチャネルバインディング」, RFC 5929, DOI 10.17487/RFC5929, , <https://www.rfc-editor.org/info/rfc5929>.
[RFC6091]
Mavrogiannopoulos, N. and D. Gillmor, 「トランスポート層セキュリティ (TLS)認証でのOpenPGP鍵の使用」, RFC 6091, DOI 10.17487/RFC6091, , <https://www.rfc-editor.org/info/rfc6091>.
[RFC6101]
Freier, A., Karlton, P., and P. Kocher, 「Secure Sockets Layer (SSL)プロトコル バージョン3.0」, RFC 6101, DOI 10.17487/RFC6101, , <https://www.rfc-editor.org/info/rfc6101>.
[RFC6176]
Turner, S. and T. Polk, 「Secure Sockets Layer(SSL)バージョン2.0の禁止」, RFC 6176, DOI 10.17487/RFC6176, , <https://www.rfc-editor.org/info/rfc6176>.
[RFC6520]
Seggelmann, R., Tuexen, M., and M. Williams, 「トランスポート層 セキュリティ(TLS)およびDatagram Transport Layer Security(DTLS)のハートビート拡張」, RFC 6520, DOI 10.17487/RFC6520, , <https://www.rfc-editor.org/info/rfc6520>.
[RFC7250]
Wouters, P., Ed., Tschofenig, H., Ed., Gilmore, J., Weiler, S., and T. Kivinen, 「トランスポート 層セキュリティ(TLS)およびDatagram Transport Layer Security (DTLS)での生の公開鍵の使用」, RFC 7250, DOI 10.17487/RFC7250, , <https://www.rfc-editor.org/info/rfc7250>.
[RFC7465]
Popov, A., 「RC4暗号 スイートの禁止」, RFC 7465, DOI 10.17487/RFC7465, , <https://www.rfc-editor.org/info/rfc7465>.
[RFC7568]
Barnes, R., Thomson, M., Pironti, A., and A. Langley, 「Secure Sockets Layerバージョン3.0の非推奨化」, RFC 7568, DOI 10.17487/RFC7568, , <https://www.rfc-editor.org/info/rfc7568>.
[RFC7624]
Barnes, R., Schneier, B., Jennings, C., Hardie, T., Trammell, B., Huitema, C., and D. Borkmann, 「広範な監視に直面した 機密性: 脅威モデルおよび問題提起」, RFC 7624, DOI 10.17487/RFC7624, , <https://www.rfc-editor.org/info/rfc7624>.
[RFC7685]
Langley, A., 「トランスポート層 セキュリティ(TLS)のClientHelloパディング拡張」, RFC 7685, DOI 10.17487/RFC7685, , <https://www.rfc-editor.org/info/rfc7685>.
[RFC7924]
Santesson, S. and H. Tschofenig, 「トランスポート層セキュリティ(TLS)の キャッシュ済み情報拡張」, RFC 7924, DOI 10.17487/RFC7924, , <https://www.rfc-editor.org/info/rfc7924>.
[RFC8305]
Schinazi, D. and T. Pauly, 「Happy Eyeballsバージョン2: 並行処理による接続性の向上」, RFC 8305, DOI 10.17487/RFC8305, , <https://www.rfc-editor.org/info/rfc8305>.
[RFC8422]
Nir, Y., Josefsson, S., and M. Pegourie-Gonnard, 「トランスポート層セキュリティ (TLS)バージョン1.2以前用の楕円曲線暗号(ECC)暗号スイート」, RFC 8422, DOI 10.17487/RFC8422, , <https://www.rfc-editor.org/info/rfc8422>.
[RFC8446]
Rescorla, E., 「トランスポート層 セキュリティ(TLS)プロトコル バージョン1.3」, RFC 8446, DOI 10.17487/RFC8446, , <https://www.rfc-editor.org/info/rfc8446>.
[RFC8447]
Salowey, J. and S. Turner, 「TLSおよびDTLSのIANAレジストリ更新」, RFC 8447, DOI 10.17487/RFC8447, , <https://www.rfc-editor.org/info/rfc8447>.
[RFC8448]
Thomson, M., 「TLS 1.3の ハンドシェイクトレース例」, RFC 8448, DOI 10.17487/RFC8448, , <https://www.rfc-editor.org/info/rfc8448>.
[RFC8449]
Thomson, M., 「TLSのレコードサイズ制限 拡張」, RFC 8449, DOI 10.17487/RFC8449, , <https://www.rfc-editor.org/info/rfc8449>.
[RFC8470]
Thomson, M., Nottingham, M., and W. Tarreau, 「HTTPにおける早期データの 使用」, RFC 8470, DOI 10.17487/RFC8470, , <https://www.rfc-editor.org/info/rfc8470>.
[RFC8773]
Housley, R., 「外部事前共有鍵を使用する 証明書ベース認証のためのTLS 1.3拡張」, RFC 8773, DOI 10.17487/RFC8773, , <https://www.rfc-editor.org/info/rfc8773>.
[RFC8844]
Thomson, M. and E. Rescorla, 「セッション記述プロトコル(SDP)とともにTLSを使用する際の 未知鍵共有攻撃」, RFC 8844, DOI 10.17487/RFC8844, , <https://www.rfc-editor.org/info/rfc8844>.
[RFC8870]
Jennings, C., Mattsson, J., McGrew, D., Wing, D., and F. Andreasen, 「DTLSおよびセキュアRTP用の 暗号化鍵トランスポート」, RFC 8870, DOI 10.17487/RFC8870, , <https://www.rfc-editor.org/info/rfc8870>.
[RFC8879]
Ghedini, A. and V. Vasiliev, 「TLS証明書圧縮」, RFC 8879, DOI 10.17487/RFC8879, , <https://www.rfc-editor.org/info/rfc8879>.
[RFC8937]
Cremers, C., Garratt, L., Smyshlyaev, S., Sullivan, N., and C. Wood, 「セキュリティプロトコルの 乱数性改善」, RFC 8937, DOI 10.17487/RFC8937, , <https://www.rfc-editor.org/info/rfc8937>.
[RFC9001]
Thomson, M., Ed. and S. Turner, Ed., 「QUICを保護するためのTLSの使用」, RFC 9001, DOI 10.17487/RFC9001, , <https://www.rfc-editor.org/info/rfc9001>.
[RFC9112]
Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., 「HTTP/1.1」, STD 99, RFC 9112, DOI 10.17487/RFC9112, , <https://www.rfc-editor.org/info/rfc9112>.
[RFC9147]
Rescorla, E., Tschofenig, H., and N. Modadugu, 「Datagram Transport Layer Security(DTLS)プロトコル バージョン1.3」, RFC 9147, DOI 10.17487/RFC9147, , <https://www.rfc-editor.org/info/rfc9147>.
[RFC9149]
Pauly, T., Schinazi, D., and C.A. Wood, 「TLSチケット 要求」, RFC 9149, DOI 10.17487/RFC9149, , <https://www.rfc-editor.org/info/rfc9149>.
[RFC9162]
Laurie, B., Messeri, E., and R. Stradling, 「証明書 透明性バージョン2.0」, RFC 9162, DOI 10.17487/RFC9162, , <https://www.rfc-editor.org/info/rfc9162>.
[RFC9257]
Housley, R., Hoyland, J., Sethi, M., and C. A. Wood, 「TLSにおける外部事前共有鍵(PSK)使用の指針」, RFC 9257, DOI 10.17487/RFC9257, , <https://www.rfc-editor.org/info/rfc9257>.
[RFC9258]
Benjamin, D. and C. A. Wood, 「TLS 1.3用外部事前共有鍵(PSK)のインポート」, RFC 9258, DOI 10.17487/RFC9258, , <https://www.rfc-editor.org/info/rfc9258>.
[RFC9261]
Sullivan, N., 「TLSのエクスポートされた認証子」, RFC 9261, DOI 10.17487/RFC9261, , <https://www.rfc-editor.org/info/rfc9261>.
[RFC9345]
Barnes, R., Iyengar, S., Sullivan, N., and E. Rescorla, 「TLSおよびDTLSの委任された資格情報」, RFC 9345, DOI 10.17487/RFC9345, , <https://www.rfc-editor.org/info/rfc9345>.
[RFC9525]
Saint-Andre, P. and R. Salz, 「TLSにおけるサービス識別情報」, RFC 9525, DOI 10.17487/RFC9525, , <https://www.rfc-editor.org/info/rfc9525>.
[RFC9847]
Salowey, J. and S. Turner, 「TLSおよびDTLSのIANAレジストリ更新」, RFC 9847, DOI 10.17487/RFC9847, , <https://www.rfc-editor.org/info/rfc9847>.
[RFC9849]
Rescorla, E., Oku, K., Sullivan, N., and C. A. Wood, 「TLS暗号化Client Hello」, RFC 9849, DOI 10.17487/RFC9849, , <https://www.rfc-editor.org/info/rfc9849>.
[RFC9963]
Benjamin, D. and A. Popov, 「TLS 1.3用レガシーRSASSA-PKCS1-v1_5コードポイント」, RFC 9963, DOI 10.17487/RFC9963, , <https://www.rfc-editor.org/info/rfc9963>.
[RSA]
Rivest, R., Shamir, A., and L. Adleman, 「デジタル署名および 公開鍵暗号システムを得るための方法」, Association for Computing Machinery(ACM), Communications of the ACM vol. 21, no. 2, pp. 120-126, DOI 10.1145/359340.359342, , <https://doi.org/10.1145/359340.359342>.
[Selfie]
Drucker, N. and S. Gueron, 「Selfie: PSKを使用するTLS 1.3への考察」, , <https://eprint.iacr.org/2019/347>.
[SIGMA]
Krawczyk, H., 「SIGMA: 認証付き Diffie-Hellmanへの「SIGn-and-MAc」アプローチおよびIKE プロトコルでの使用」, Springer Berlin Heidelberg, コンピューターサイエンス講義ノート pp. 400-425, DOI 10.1007/978-3-540-45146-4_24, ISBN ["9783540406747", "9783540451464"], , <https://doi.org/10.1007/978-3-540-45146-4_24>.
[SLOTH]
Bhargavan, K. and G. Leurent, 「トランスクリプト衝突攻撃: TLS、IKE、 およびSSHの認証破壊」, Internet Society, 2016年ネットワークおよび分散システムセキュリティ シンポジウム予稿集, DOI 10.14722/ndss.2016.23418, , <https://doi.org/10.14722/ndss.2016.23418>.
[SSL2]
Hickman, K. E., 「SSL プロトコル」, , <https://datatracker.ietf.org/doc/html/draft-hickman-netscape-ssl-00>.
[TIMING]
Boneh, D. and D. Brumley, 「リモートタイミング攻撃は実用的である」, 第12回USENIXセキュリティシンポジウム(USENIX Security 03), , <https://www.usenix.org/conference/12th-usenix-security-symposium/remote-timing-attacks-are-practical>.
[X501]
ITU-T, 「情報技術 - 開放型 システム間相互接続 - ディレクトリ: モデル」, ITU-T 勧告 X.501, ISO/IEC 9594-2:2020, , <https://www.itu.int/rec/T-REC-X.501-201910-I/en>.

付録A. 状態機械

この付録では、クライアントおよびサーバーのハンドシェイクにおける 正当な状態遷移を要約する。状態名(すべて大文字、例えば START)には形式的な意味はなく、理解しやすくするために 提供される。特定の状況でのみ実行される操作は []内に示す。「K_{send,recv} = foo」という表記は、「送信/受信 鍵を指定された鍵に設定する」ことを意味する。

A.1. クライアント

                           START <----+
       ClientHelloを送信 |        | HelloRetryRequestを受信
       [K_send = 早期データ] |        |
                             v        |
        +->               WAIT_SH ----+
        |                    | ServerHelloを受信
        |                    | K_recv = ハンドシェイク
  早期 |                    V
データを |                 WAIT_EE
 送信 |                    | EncryptedExtensionsを受信
 可能 |          +---------+-------+
        |    PSKを |                 | 証明書を使用
        |      使用 |                 v
        |          |            WAIT_CERT_CR
        |          |      Certificateを受信 |       | CertificateRequestを受信
        |          |                       |       v
        |          |                       |    WAIT_CERT
        |          |                       |       | Certificateを受信
        |          |                       v       v
        |          |                        WAIT_CV
        |          |                             | CertificateVerifyを受信
        |          +-> WAIT_FINISHED <-+
        |                  | Finishedを受信
        +->                | [EndOfEarlyDataを送信]
                           | K_send = ハンドシェイク
                           | [Certificate [+ CertificateVerify]を送信]
 ここ以降                | Finishedを送信
アプリデータを -->            | K_send = K_recv = アプリケーション
 送信可能                v
                       CONNECTED

上記の遷移では、クライアントがServerHello後のメッセージに由来する アラートを、平文または早期データ鍵で送信する場合があることに注意されたい。 クライアントがそのようなアラートを送信する必要がある場合、可能であれば まずハンドシェイク鍵へ鍵を変更することが望ましい

A.2. サーバー

                             START <-----+
              ClientHelloを受信 |         | HelloRetryRequestを送信
                               v         |
                            RECVD_CH ----+
                               | パラメーターを選択
                               v
                            NEGOTIATED
                               | ServerHelloを送信
                               | K_send = ハンドシェイク
                               | EncryptedExtensionsを送信
                               | [CertificateRequestを送信]
アプリデータを                 | [Certificate + CertificateVerifyを送信]
送信可能                       | Finishedを送信
ここ以降 -->                  | K_send = アプリケーション
                       +--------+--------+
             0-RTTなし |                 | 0-RTT
                      |                 |
  K_recv = ハンドシェイク  |                 | K_recv = 早期データ
[復号エラーを読み飛ばす] |    +------> WAIT_EOED --+
                      |    |       早期 | EndOfEarlyDataを受信
                      |    |   データを受信 |       | K_recv = ハンドシェイク
                      |    +------------+       |
                      |                         |
                      +-> WAIT_FLIGHT2 <--------+
                               |
                      +--------+--------+
              認証なし |                 | 証明書ベースのクライアント認証
                      |                 |
                      |                 v
                      |             WAIT_CERT
                      |    空のCertificateを受信 |       | Certificateを受信
                      |                       |       v
                      |                       |    WAIT_CV
                      |                       |       | CertificateVerifyを
                      |                       v       | 受信
                      +-> WAIT_FINISHED <---+
                               | Finishedを受信
                               | K_recv = アプリケーション
                               v
                           CONNECTED

付録B. プロトコルデータ構造および 定数値

この付録では、規範的なプロトコル型および定数の定義を 提供する。「_RESERVED」として列挙される値は、 以前のバージョンのTLSで使用されていたものであり、完全を期すためにここに 列挙されている。TLS 1.3実装はこれらを送信してはならないが、 古いTLS実装から受信する場合がある。

B.1. レコード層

   enum {
       invalid(0),
       change_cipher_spec(20),
       alert(21),
       handshake(22),
       application_data(23),
       (255)
   } ContentType;

   struct {
       ContentType type;
       ProtocolVersion legacy_record_version;
       uint16 length;
       opaque fragment[TLSPlaintext.length];
   } TLSPlaintext;

   struct {
       opaque content[TLSPlaintext.length];
       ContentType type;
       uint8 zeros[length_of_padding];
   } TLSInnerPlaintext;

   struct {
       ContentType opaque_type = application_data; /* 23 */
       ProtocolVersion legacy_record_version = 0x0303; /* TLS v1.2 */
       uint16 length;
       opaque encrypted_record[TLSCiphertext.length];
   } TLSCiphertext;

B.2. アラートメッセージ

   enum { warning(1), fatal(2), (255) } AlertLevel;

   enum {
       close_notify(0),
       unexpected_message(10),
       bad_record_mac(20),
       decryption_failed_RESERVED(21),
       record_overflow(22),
       decompression_failure_RESERVED(30),
       handshake_failure(40),
       no_certificate_RESERVED(41),
       bad_certificate(42),
       unsupported_certificate(43),
       certificate_revoked(44),
       certificate_expired(45),
       certificate_unknown(46),
       illegal_parameter(47),
       unknown_ca(48),
       access_denied(49),
       decode_error(50),
       decrypt_error(51),
       export_restriction_RESERVED(60),
       protocol_version(70),
       insufficient_security(71),
       internal_error(80),
       inappropriate_fallback(86),
       user_canceled(90),
       no_renegotiation_RESERVED(100),
       missing_extension(109),
       unsupported_extension(110),
       certificate_unobtainable_RESERVED(111),
       unrecognized_name(112),
       bad_certificate_status_response(113),
       bad_certificate_hash_value_RESERVED(114),
       unknown_psk_identity(115),
       certificate_required(116),
       general_error(117),
       no_application_protocol(120),
       (255)
   } AlertDescription;

   struct {
       AlertLevel level;
       AlertDescription description;
   } Alert;

B.3. ハンドシェイクプロトコル

   enum {
       hello_request_RESERVED(0),
       client_hello(1),
       server_hello(2),
       hello_verify_request_RESERVED(3),
       new_session_ticket(4),
       end_of_early_data(5),
       hello_retry_request_RESERVED(6),
       encrypted_extensions(8),
       certificate(11),
       server_key_exchange_RESERVED(12),
       certificate_request(13),
       server_hello_done_RESERVED(14),
       certificate_verify(15),
       client_key_exchange_RESERVED(16),
       finished(20),
       certificate_url_RESERVED(21),
       certificate_status_RESERVED(22),
       supplemental_data_RESERVED(23),
       key_update(24),
       message_hash(254),
       (255)
   } HandshakeType;

   struct {
       HandshakeType msg_type;    /* ハンドシェイクの種類 */
       uint24 length;             /* メッセージ内の残りのバイト数 */
       select (Handshake.msg_type) {
           case client_hello:          ClientHello;
           case server_hello:          ServerHello;
           case end_of_early_data:     EndOfEarlyData;
           case encrypted_extensions:  EncryptedExtensions;
           case certificate_request:   CertificateRequest;
           case certificate:           Certificate;
           case certificate_verify:    CertificateVerify;
           case finished:              Finished;
           case new_session_ticket:    NewSessionTicket;
           case key_update:            KeyUpdate;
       };
   } Handshake;

B.3.1. 鍵交換 メッセージ

   uint16 ProtocolVersion;
   opaque Random[32];

   uint8 CipherSuite[2];    /* 暗号スイートセレクター */

   struct {
       ProtocolVersion legacy_version = 0x0303;    /* TLS v1.2 */
       Random random;
       opaque legacy_session_id<0..32>;
       CipherSuite cipher_suites<2..2^16-2>;
       opaque legacy_compression_methods<1..2^8-1>;
       Extension extensions<7..2^16-1>;
   } ClientHello;

   struct {
       ProtocolVersion legacy_version = 0x0303;    /* TLS v1.2 */
       Random random;
       opaque legacy_session_id_echo<0..32>;
       CipherSuite cipher_suite;
       uint8 legacy_compression_method = 0;
       Extension extensions<6..2^16-1>;
   } ServerHello;

   struct {
       ExtensionType extension_type;
       opaque extension_data<0..2^16-1>;
   } Extension;

   enum {
       server_name(0),                             /* RFC 6066, 9261 */
       status_request(5),                          /* RFC 6066, 9846 */
       supported_groups(10),                       /* RFC 7919, 9846 */
       signature_algorithms(13),                   /* RFC 9846 */
       use_srtp(14),                               /* RFC 5764 */
       heartbeat(15),                              /* RFC 6520 */
       application_layer_protocol_negotiation(16), /* RFC 7301 */
       client_certificate_type(19),                /* RFC 7250 */
       server_certificate_type(20),                /* RFC 7250 */
       padding(21),                                /* RFC 7685 */
       compress_certificate(27),                   /* RFC 8879 */
       record_size_limit(28),                      /* RFC 8449 */
       delegated_credential(34),                   /* RFC 9345 */
       supported_ekt_ciphers(39),                  /* RFC 8870 */
       pre_shared_key(41),                         /* RFC 9846 */
       early_data(42),                             /* RFC 9846 */
       supported_versions(43),                     /* RFC 9846 */
       cookie(44),                                 /* RFC 9846 */
       psk_key_exchange_modes(45),                 /* RFC 9846 */
       certificate_authorities(47),                /* RFC 9846 */
       oid_filters(48),                            /* RFC 9846 */
       post_handshake_auth(49),                    /* RFC 9846 */
       signature_algorithms_cert(50),              /* RFC 9846 */
       key_share(51),                              /* RFC 9846 */
       transparency_info(52),                      /* RFC 9162 */
       external_id_hash(55),                       /* RFC 8844 */
       external_session_id(56),                    /* RFC 8844 */
       quic_transport_parameters(57),              /* RFC 9001 */
       ticket_request(58),                         /* RFC 9149 */
       ech_outer_extensions(64768),                /* RFC 9849 */
       encrypted_client_hello(65037),              /* RFC 9849 */
       (65535)
   } ExtensionType;

   struct {
       NamedGroup group;
       opaque key_exchange<1..2^16-1>;
   } KeyShareEntry;

   struct {
       KeyShareEntry client_shares<0..2^16-1>;
   } KeyShareClientHello;

   struct {
       NamedGroup selected_group;
   } KeyShareHelloRetryRequest;

   struct {
       KeyShareEntry server_share;
   } KeyShareServerHello;

   struct {
       uint8 legacy_form = 4;
       opaque X[coordinate_length];
       opaque Y[coordinate_length];
   } UncompressedPointRepresentation;

   enum { psk_ke(0), psk_dhe_ke(1), (255) } PskKeyExchangeMode;

   struct {
       PskKeyExchangeMode ke_modes<1..255>;
   } PskKeyExchangeModes;

   struct {} Empty;

   struct {
       select (Handshake.msg_type) {
           case new_session_ticket:   uint32 max_early_data_size;
           case client_hello:         Empty;
           case encrypted_extensions: Empty;
       };
   } EarlyDataIndication;

   struct {
       opaque identity<1..2^16-1>;
       uint32 obfuscated_ticket_age;
   } PskIdentity;

   opaque PskBinderEntry<32..255>;

   struct {
       PskIdentity identities<7..2^16-1>;
       PskBinderEntry binders<33..2^16-1>;
   } OfferedPsks;

   struct {
       select (Handshake.msg_type) {
           case client_hello: OfferedPsks;
           case server_hello: uint16 selected_identity;
       };
   } PreSharedKeyExtension;
B.3.1.1. バージョン 拡張
   struct {
       select (Handshake.msg_type) {
           case client_hello:
                ProtocolVersion versions<2..254>;

           case server_hello: /* およびHelloRetryRequest */
                ProtocolVersion selected_version;
       };
   } SupportedVersions;
B.3.1.3. 署名アルゴリズム拡張
   enum {
       /* RSASSA-PKCS1-v1_5アルゴリズム */
       rsa_pkcs1_sha256(0x0401),
       rsa_pkcs1_sha384(0x0501),
       rsa_pkcs1_sha512(0x0601),

       /* ECDSAアルゴリズム */
       ecdsa_secp256r1_sha256(0x0403),
       ecdsa_secp384r1_sha384(0x0503),
       ecdsa_secp521r1_sha512(0x0603),

       /* 公開鍵OIDがrsaEncryptionであるRSASSA-PSSアルゴリズム */
       rsa_pss_rsae_sha256(0x0804),
       rsa_pss_rsae_sha384(0x0805),
       rsa_pss_rsae_sha512(0x0806),

       /* EdDSAアルゴリズム */
       ed25519(0x0807),
       ed448(0x0808),

       /* 公開鍵OIDがRSASSA-PSSであるRSASSA-PSSアルゴリズム */
       rsa_pss_pss_sha256(0x0809),
       rsa_pss_pss_sha384(0x080a),
       rsa_pss_pss_sha512(0x080b),

       /* レガシーアルゴリズム */
       rsa_pkcs1_sha1(0x0201),
       ecdsa_sha1(0x0203),

       /* 予約済みコードポイント */
       obsolete_RESERVED(0x0000..0x0200),
       dsa_sha1_RESERVED(0x0202),
       obsolete_RESERVED(0x0204..0x0400),
       dsa_sha256_RESERVED(0x0402),
       obsolete_RESERVED(0x0404..0x0500),
       dsa_sha384_RESERVED(0x0502),
       obsolete_RESERVED(0x0504..0x0600),
       dsa_sha512_RESERVED(0x0602),
       obsolete_RESERVED(0x0604..0x06FF),
       private_use(0xFE00..0xFFFF),
       (0xFFFF)
   } SignatureScheme;

   struct {
       SignatureScheme supported_signature_algorithms<2..2^16-2>;
   } SignatureSchemeList;
B.3.1.4. サポートされるグループ拡張
   enum {
       unallocated_RESERVED(0x0000),

       /* 楕円曲線グループ(ECDHE) */
       obsolete_RESERVED(0x0001..0x0016),
       secp256r1(0x0017), secp384r1(0x0018), secp521r1(0x0019),
       obsolete_RESERVED(0x001A..0x001C),
       x25519(0x001D), x448(0x001E),

       /* 有限体グループ(DHE) */
       ffdhe2048(0x0100), ffdhe3072(0x0101), ffdhe4096(0x0102),
       ffdhe6144(0x0103), ffdhe8192(0x0104),

       /* 予約済みコードポイント */
       ffdhe_private_use(0x01FC..0x01FF),
       ecdhe_private_use(0xFE00..0xFEFF),
       obsolete_RESERVED(0xFF01..0xFF02),
       (0xFFFF)
   } NamedGroup;

   struct {
       NamedGroup named_group_list<2..2^16-1>;
   } NamedGroupList;

「obsolete_RESERVED」の範囲内の値は、 以前のバージョンのTLSで使用されており、TLS 1.3実装はこれらを提示またはネゴシエート してはならない。 廃止された曲線には、既知または理論上のさまざまな弱点があるか、 使用実績が非常に少なく、場合によっては意図しない サーバー設定の問題だけが原因で使用されていた。 これらは一般的な使用にはもはや適切とは見なされず、 潜在的に安全でないと想定すべきである。ここで規定する 曲線の集合は、現在配置され、適切に設定されたすべてのTLS実装との 相互運用性に十分である。

B.3.2. サーバー パラメーターメッセージ

   opaque DistinguishedName<1..2^16-1>;

   struct {
       DistinguishedName authorities<3..2^16-1>;
   } CertificateAuthoritiesExtension;

   struct {
       opaque certificate_extension_oid<1..2^8-1>;
       opaque certificate_extension_values<0..2^16-1>;
   } OIDFilter;

   struct {
       OIDFilter filters<0..2^16-1>;
   } OIDFilterExtension;

   struct {} PostHandshakeAuth;

   struct {
       Extension extensions<0..2^16-1>;
   } EncryptedExtensions;

   struct {
       opaque certificate_request_context<0..2^8-1>;
       Extension extensions<0..2^16-1>;
   } CertificateRequest;

B.3.3. 認証 メッセージ

   enum {
       X509(0),
       OpenPGP_RESERVED(1),
       RawPublicKey(2),
       (255)
   } CertificateType;

   struct {
       select (certificate_type) {
           case RawPublicKey:
             /* RFC 7250のASN.1_subjectPublicKeyInfo */
             opaque ASN1_subjectPublicKeyInfo<1..2^24-1>;

           case X509:
             opaque cert_data<1..2^24-1>;
       };
       Extension extensions<0..2^16-1>;
   } CertificateEntry;

   struct {
       opaque certificate_request_context<0..2^8-1>;
       CertificateEntry certificate_list<0..2^24-1>;
   } Certificate;

   struct {
       SignatureScheme algorithm;
       opaque signature<0..2^16-1>;
   } CertificateVerify;

   struct {
       opaque verify_data[Hash.length];
   } Finished;

B.3.4. チケット 確立

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

B.3.5. 鍵の更新

   struct {} EndOfEarlyData;

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

   struct {
       KeyUpdateRequest request_update;
   } KeyUpdate;

B.4. 暗号スイート

暗号スイートは、HKDFとともに使用するAEADアルゴリズムおよびハッシュ アルゴリズムの組を定義する。 暗号スイート名は次の命名規則に従う。

   CipherSuite TLS_AEAD_HASH = VALUE;
表4: 暗号スイート名の 構造
構成要素 内容
TLS 文字列「TLS」
AEAD レコード保護に使用するAEAD アルゴリズム
HASH HKDFおよび Transcript-Hashとともに使用するハッシュアルゴリズム
VALUE この暗号スイートに割り当てられた 2バイトのID

本仕様は、TLS 1.3で使用する次の暗号スイートを定義する。

表5: 暗号スイート一覧
説明
TLS_AES_128_GCM_SHA256 {0x13,0x01}
TLS_AES_256_GCM_SHA384 {0x13,0x02}
TLS_CHACHA20_POLY1305_SHA256 {0x13,0x03}
TLS_AES_128_CCM_SHA256 {0x13,0x04}
TLS_AES_128_CCM_8_SHA256 {0x13,0x05}

対応するAEADアルゴリズムAEAD_AES_128_GCM、AEAD_AES_256_GCM、および AEAD_AES_128_CCMは[RFC5116]で定義される。 AEAD_CHACHA20_POLY1305は [RFC8439]で定義される。AEAD_AES_128_CCM_8は [RFC6655]で定義される。対応する ハッシュアルゴリズムは[SHS]で定義される。

TLS 1.3は以前のバージョンのTLSと同じ暗号スイート空間を使用するが、 TLS 1.3の暗号スイートは異なる方法で定義され、 対称暗号だけを規定するため、TLS 1.2では使用できない。同様に、 TLS 1.2以前の暗号スイートはTLS 1.3では使用できない。

新しい暗号スイート値は、 第11節で説明されているように IANAによって割り当てられる。

付録C. 実装上の注意事項

TLSプロトコルでは、多くの一般的なセキュリティ上の誤りを防止できない。この付録では、 実装者を支援するためにいくつかの推奨事項を提供する。 [RFC8448]は、TLS 1.3 ハンドシェイクのテストベクトルを提供する。

C.1. 乱数 生成およびシード設定

TLSには、暗号学的に安全な疑似乱数生成器 (CSPRNG)が必要である。 高性能かつ適切に安全なCSPRNGは、ほとんどのオペレーティング システムによって提供されるか、暗号ライブラリから取得できる。 新しいものを作成するよりも、既存のCSPRNG実装を使用することが 推奨される。適切な暗号ライブラリの多くは、 すでに有利なライセンス条件で利用できる。それらが 不十分である場合、[RFC4086]が 乱数値の生成に関する指針を提供する。

TLSは、乱数値を(1)ClientHelloおよびServerHello内の 公開Random値などの公開プロトコルフィールドで使用し、(2) 鍵素材の生成に使用する。適切に動作するCSPRNGでは、 出力からCSPRNGの状態を判定することは現実的でないため、 セキュリティ上の問題は生じない。ただし、壊れたCSPRNGでは、 攻撃者が公開出力を使用してCSPRNGの内部状態を判定し、 それによって鍵素材を予測できる可能性がある。 これは[CHECKOWAY]および [DSA-1571-1]で文書化されている。

実装は、公開値と秘密値の生成に個別のCSPRNGを使用することで、 この形式の攻撃に対する追加のセキュリティを提供できる。

[RFC8937]は、 セキュリティプロトコル実装が長期秘密鍵および決定論的署名関数を使用して、 その(疑似)乱数生成器を強化する方法を説明する。これにより、 壊れた、またはその他の方法で侵害された乱数生成器による 乱数性が改善される。

C.2. 証明書および 認証

実装は証明書の完全性を検証する責任を負い、 一般に証明書失効メッセージをサポートすることが望ましい。第4.5.1.1節を参照されたい。アプリケーションプロファイルから 特定の指示がない場合、信頼できる認証局 (CA)によって適切に署名されていることを保証するため、 証明書を常に検証することが望ましい。 トラストアンカーの選択および追加は非常に慎重に行うことが望ましい。 ユーザーは証明書およびトラストアンカーに関する情報を表示できることが望ましい。 アプリケーションは最小および最大の鍵サイズも 強制することが望ましい。例えば、 2048ビットRSAまたは224ビットECDSAより弱い鍵または署名を含む 証明パスは、安全なアプリケーションには適切でない。

一部のプロトコルでは、クライアントモードとサーバーモードの両方で 同じ証明書を使用することが一般的であることに注意されたい。この設定は 広範には分析されておらず、この場合に上位レベルのセマンティクスについて 曖昧さが生じないことを保証する責任は、 上位レベルプロトコルにある。

C.3. 実装上の 落とし穴

実装経験から、以前のTLS仕様の一部は理解が容易でなく、 相互運用性およびセキュリティ上の問題の原因となってきたことが分かっている。 これらの領域の多くは本文書で明確化されているが、この付録には、 実装者が特に注意する必要がある最も重要な事項の短い一覧を示す。

TLSプロトコルの問題:

  • 複数のTLSレコードに断片化されたハンドシェイクメッセージを 正しく処理しているか(第 5.1節を参照)?複数の小さな断片に分割されたClientHelloなどの 境界事例を正しく処理しているか? 最大断片サイズを超えるハンドシェイクメッセージを断片化しているか? 特に、CertificateおよびCertificateRequest ハンドシェイクメッセージは、断片化が必要になるほど大きくなる場合がある。 [RFC8879]で定義される証明書圧縮を使用して、 断片化のリスクを低減できる。

  • 暗号化されていないすべてのTLS レコードで、TLSレコード層のバージョン番号を無視しているか (付録 Eを参照)?

  • TLS 1.3以降をサポートするすべての可能な設定から、 SSL、RC4、EXPORT暗号、および MD5(「signature_algorithms」拡張による)へのすべてのサポートを完全に削除し、 これらの廃止された機能を使用しようとした場合に正しく失敗することを 保証したか (付録Eを参照)?

  • 未知の拡張を含め、 ClientHello内のTLS拡張を正しく処理しているか?

  • サーバーがクライアント証明書を要求したが、 適切な証明書が利用できない場合、 メッセージ全体を省略するのではなく、 空のCertificateメッセージを正しく送信しているか (第4.5.1節を参照)?

  • AEAD-Decryptによって生成された平文断片を処理し、 末尾からContentTypeを走査する際、 ピアがすべて0からなる不正な平文を送信した場合に、 平文の先頭を越えて走査しないようにしているか?

  • ClientHello内の認識できない暗号スイート (第4.2.2節)、 hello拡張 (第4.3節)、名前付きグループ (第4.3.7節)、鍵共有 (第4.3.8節)、 サポートされるバージョン(第 4.3.1節)、 および署名アルゴリズム(第4.3.3節)を 適切に無視しているか?

  • サーバーとして、互換性のある非対称鍵交換グループを サポートするが、「key_share」拡張でそれを予測していないクライアントへ HelloRetryRequestを送信しているか?クライアントとして、 サーバーからのHelloRetryRequestを正しく処理しているか?

暗号学的詳細:

  • タイミング攻撃 [TIMING]を防ぐため、 どのような対策を使用しているか?

  • Diffie-Hellman鍵交換を使用する場合、 ネゴシエートされた鍵の先頭の0バイトを正しく保持しているか (第7.4.1節を参照)?

  • TLSクライアントは、サーバーが送信した Diffie-Hellmanパラメーターが受け入れ可能であることを確認しているか (第4.3.8.1節を参照)?

  • Diffie-Hellman秘密値、ECDSAの「k」パラメーター、 およびその他のセキュリティ上重要な値を生成する際、 強力で、最も重要なこととして適切にシードされた乱数 生成器を使用しているか (付録C.1を参照)? 実装は、[RFC6979]で規定される 「決定論的ECDSA」を実装することが 推奨される。決定論的ECDSAおよびEdDSAなどの 純粋に決定論的な楕円曲線暗号(ECC)署名は、 容易にアクセスできるモノのインターネット(IoT)機器において、 特定のサイドチャネル攻撃および故障注入攻撃に対して 脆弱な場合があることに注意されたい。

  • Diffie-Hellman公開鍵値および共有秘密を グループサイズまで0でパディングしているか (第 4.3.8.1節および第7.4.1節を参照)?

  • RSA-CRT 鍵漏えい[FW15]を防ぐため、 署名を作成した後に検証しているか?

C.4. クライアントおよびサーバーの 追跡防止

クライアントは、複数の接続でチケットを再利用 しないことが望ましい。チケットを再利用すると、 受動的な観測者が異なる接続を関連付けられる。 チケットを発行するサーバーは、クライアントが使用する可能性のある接続数以上の チケットを提示することが望ましい。例えば、HTTP/1.1 [RFC9112]を使用するウェブブラウザーは、 サーバーに対して6つの接続を開く場合がある。サーバーは、 接続ごとに新しいチケットを発行することが望ましい。 これにより、クライアントは新しい接続を作成するとき、 常に新しいチケットを使用できる。

サーバーにチケットを提示すると、 サーバーも異なる接続を関連付けられるようになる。 これはチケットの再利用とは無関係に可能である。クライアント アプリケーションは、関連付けられることを意図しない接続間で チケットを提示しないことが望ましい。 例えば、[FETCH]は、 ウェブブラウザー内のキャッシュ検索を分離するための ネットワークパーティションキーを定義する。

外部識別情報のラベルは、 ユーザーの識別情報に関する追加情報を提供しないよう選択することが 推奨される。例えば、ラベルにメールアドレスが含まれる場合、 暗号化されるクライアントのCertificateとは異なり、 受動的攻撃者に対してユーザーを容易に識別させる。 このリスクを回避する潜在的な方法には、 (1)ランダムな識別情報ラベルを使用する、 (2)サーバーが認識する鍵で識別情報を事前に暗号化する、または (3)Encrypted Client Hello [RFC9849]を 使用する、などがある。

外部PSK識別情報を複数の接続で使用する場合、 一般に外部の観測者は、接続をまたいで クライアントおよび/またはサーバーを追跡できる。 Encrypted Client Hello [RFC9849]を 使用することでこのリスクを軽減できるほか、 PSK識別情報をローテーションまたは暗号化するTLS外部の機構でも 軽減できる。

C.5. 未認証 動作

以前のバージョンのTLSは、 匿名Diffie-Hellmanに基づく明示的に未認証の暗号スイートを提供していた。 これらのモードはTLS 1.3で非推奨となった。 ただし、次を含む複数の方法により、 検証可能なサーバー認証を提供しないパラメーターを ネゴシエートすることは依然として可能である。

  • 生の公開鍵[RFC7250]

  • 証明書に含まれる公開鍵を使用するが、 証明書チェーンまたはその内容を検証しない。

いずれの技法も単独で使用すると中間者攻撃に対して脆弱であり、 したがって一般的な使用には安全でない。ただし、 サーバーの公開鍵の帯域外検証、初回使用時の信頼、 またはチャネルバインディングなどの機構を介して、 そのような接続を外部認証機構に結び付けることも可能である (ただし、[RFC5929]で説明される チャネルバインディングはTLS 1.3には定義されていない)。 そのような機構を使用しない場合、接続は能動的な中間者攻撃に対する 保護を持たない。明示的な設定または特定のアプリケーション プロファイルがない限り、アプリケーションはTLSを そのような方法で使用してはならない

付録D. TLS 1.2の更新

本文書で使用される名称に合わせるため、 [RFC5246]の次の用語を改名する。

これに対応して、[RFC7627]で定義される拡張を 「Extended Main Secret」拡張に改名する。拡張コードポイントは 「extended_main_secret」に改名する。互換性のため、[RFC7627]の第4節にあるPRF関数の labelパラメーターは変更しない。

付録E. 後方互換性

TLSプロトコルは、異なるバージョンのTLSをサポートする可能性がある エンドポイント間でバージョンをネゴシエートする組み込み機構を提供する。

TLS 1.xおよびSSL 3.0は、互換性のあるClientHelloメッセージを使用する。ClientHello形式の 互換性が維持され、クライアントとサーバーの両方がサポートするプロトコルバージョンが 少なくとも1つ存在する限り、サーバーは将来のバージョンのTLSを使用しようとする クライアントも処理できる。

以前のバージョンのTLSでは、レコード層のバージョン番号 (TLSPlaintext.legacy_record_versionおよび TLSCiphertext.legacy_record_version)をさまざまな目的に使用していた。 TLS 1.3以降、このフィールドは非推奨である。 TLSPlaintext.legacy_record_versionの値は、すべての実装が 無視しなければならない。 TLSCiphertext.legacy_record_versionの値は、 保護解除時の追加データに含まれるが、それ以外では 無視してもよく、 または固定定数値と一致することを 検証してもよい。 バージョンネゴシエーションは、ハンドシェイクのバージョン (ClientHello.legacy_versionおよびServerHello.legacy_version、ならびに ClientHello、HelloRetryRequest、およびServerHelloの「supported_versions」拡張) だけを使用して実行される。 古いエンドポイントとの相互運用性を最大化するため、 TLS 1.0~1.2の使用をネゴシエートする実装は、 ServerHelloおよびそれ以降のすべてのレコードについて、 レコード層のバージョン番号をネゴシエートされたバージョンに 設定することが望ましい

過去の非標準動作および誤設定された配置との互換性を最大化するため、 すべての実装は、以前のTLSバージョンのハンドシェイクを処理する場合でも、 本文書の想定に基づく証明パスの検証をサポートすることが 望ましい第4.5.1.2節を参照)。

TLS 1.2以前は、ハンドシェイクトランスクリプトの大部分を秘密および 導出鍵へ取り込む「Extended Main Secret」[RFC7627]拡張をサポートしていた。 この拡張は付録Dで改名されたことに注意されたい。TLS 1.3では常にサーバーのFinishedまでのトランスクリプトをハッシュするため、 TLS 1.3と以前のバージョンの両方をサポートする実装は、 TLS 1.3を使用する場合は常に、 APIでExtended Main Secret拡張の使用を示すことが 望ましい

E.1. 古いサーバーとの ネゴシエーション

TLS 1.3をサポートしないサーバーとのネゴシエーションを望む TLS 1.3クライアントは、 ClientHello.legacy_versionに0x0303(TLS 1.2)を含み、 「supported_versions」拡張に正しいバージョンを含む、 通常のTLS 1.3 ClientHelloを送信する。サーバーがTLS 1.3をサポートしない場合、 より古いバージョン番号を含むServerHelloで応答する。 クライアントがこのバージョンの使用に同意する場合、 ネゴシエーションは、ネゴシエートされたプロトコルに適した方法で続行される。 再開用チケットを使用するクライアントは、 以前にネゴシエートされたバージョンを使用して接続を開始することが 望ましい

0-RTTデータは古いサーバーと互換性がなく、 サーバーがTLS 1.3をサポートしていると分かっていない限り、 送信しないことが望ましい付録E.3を参照されたい。

サーバーが選択したバージョンをクライアントがサポートしていない (または受け入れられない)場合、クライアントは 「protocol_version」アラートによってハンドシェイクを 中止しなければならない

一部のレガシーサーバー実装は、TLS仕様を適切に実装しておらず、 認識できないTLS拡張またはバージョンに遭遇すると、 接続を中止することが知られている。 不具合のあるサーバーとの相互運用性は、 本文書の範囲外である複雑な問題である。 後方互換性のある接続をネゴシエートするために、 複数回の接続試行が必要になる場合があるが、 この方法はダウングレード攻撃に対して脆弱であり、 推奨されない

E.2. 古いクライアントとの ネゴシエーション

TLSサーバーは、自身がサポートする最も高いバージョンより 小さいバージョン番号を示すClientHelloを受信する場合もある。 「supported_versions」拡張が存在する場合、サーバーは 第4.3.1節で説明されるように、 その拡張を使用してネゴシエートしなければならない。 「supported_versions」拡張が存在しない場合、サーバーは ClientHello.legacy_versionとTLS 1.2のうち小さい方を ネゴシエートしなければならない。 例えば、サーバーがTLS 1.0、1.1、および1.2をサポートし、 legacy_versionがTLS 1.0である場合、 サーバーはTLS 1.0 ServerHelloで続行する。 「supported_versions」拡張が存在せず、 サーバーがClientHello.legacy_versionより大きいバージョンだけをサポートする場合、 サーバーは「protocol_version」アラートによってハンドシェイクを 中止しなければならない

以前のバージョンのTLSでは、 すべての場合についてレコード層のバージョン番号 (TLSPlaintext.legacy_record_version)の値を明確に規定していなかったことに注意されたい。 サーバーはこのフィールドでさまざまなTLS 1.xバージョンを受信するが、 その値は常に無視しなければならない

E.3. 0-RTTの後方 互換性

0-RTTデータは古いサーバーと互換性がない。 古いサーバーはClientHelloに対して古いServerHelloで応答するが、 0-RTTデータを正しく読み飛ばさず、 ハンドシェイクを完了できない。 これは、クライアントが0-RTTを使用しようとする場合、 特に複数サーバーによる配置で問題を引き起こす可能性がある。 例えば、ある配置では、一部のサーバーにTLS 1.3を実装し、 一部にTLS 1.2を実装する形でTLS 1.3を段階的に配置する場合や、 TLS 1.3の配置がTLS 1.2へダウングレードされる場合がある。

0-RTTデータの送信を試みるクライアントは、 TLS 1.2以前のServerHelloを受信した場合、 接続を失敗させなければならない。 その後、0-RTTを無効にして接続を再試行できる。 ダウングレード攻撃を回避するため、 クライアントはTLS 1.3ではなく、0-RTTだけを無効にすることが 望ましい

このエラー状態を回避するため、 複数サーバーによる配置では、 0-RTTを有効にする前に、 0-RTTを使用しないTLS 1.3を均一かつ安定して配置することが 望ましい

E.4. ミドルボックス 互換モード

実環境での測定 [Ben17a] [Ben17b] [Res17a] [Res17b]により、TLSクライアント/サーバーの組が TLS 1.3をネゴシエートすると、 かなりの数のミドルボックスが不正に動作することが判明している。 TLS 1.3ハンドシェイクをTLS 1.2ハンドシェイクにより近く見せることで、 実装はこれらのミドルボックスを通過して接続できる可能性を高められる。

  • クライアントは、第4.2.2節のlegacy_session_idの項で説明されているように、 ClientHelloで常に空でないセッションIDを提供する。

  • 早期データを提示しない場合、 クライアントは2番目のフライトの直前に、 ダミーのchange_cipher_specレコード (第5節の第3段落を参照)を送信する。 これは、2番目のClientHelloの前でも、 暗号化されたハンドシェイクフライトの前でもよい。 早期データを提示する場合、 このレコードは最初のClientHelloの直後に配置される。

  • サーバーは、最初のハンドシェイクメッセージの直後に、 ダミーのchange_cipher_specレコードを送信する。 これはServerHelloの後でも、 HelloRetryRequestの後でもよい。

これらの変更を組み合わせることで、 TLS 1.3ハンドシェイクはTLS 1.2のセッション再開に似たものとなり、 ミドルボックスを通過して正常に接続できる可能性が高まる。 この「互換モード」は部分的にネゴシエートされる。 クライアントはセッションIDを提供するかどうかを選択でき、 サーバーはそれをエコーしなければならない。 いずれの側も、ピアが無視しなければならないため、 ハンドシェイク中の任意の時点でchange_cipher_specを送信できるが、 クライアントが空でないセッションIDを送信する場合、 サーバーはこの付録で説明するようにchange_cipher_specを 送信しなければならない

E.5. 後方互換性に関連する セキュリティ上の制限

古いバージョンのTLSの使用をネゴシエートする実装は、 利用可能な場合、前方秘匿性を持つAEAD暗号スイートを 優先することが望ましい

RC4暗号スイートのセキュリティは、 [RFC7465]で示された理由により 不十分と見なされる。実装は、いかなる理由でも、 どのTLSバージョンについてもRC4暗号スイートを提示またはネゴシエート してはならない

古いバージョンのTLSでは、強度が非常に低い暗号の使用が許可されていた。 強度が112ビット未満の暗号は、いかなる理由でも、 どのTLSバージョンについても提示またはネゴシエート してはならない

SSL 2.0 [SSL2]、SSL 3.0 [RFC6101]、TLS 1.0 [RFC2246]、およびTLS 1.1 [RFC4346]のセキュリティは、 [RFC6176][RFC7568]、および[RFC8996]で列挙された理由により不十分と見なされ、 いかなる理由でもネゴシエートしてはならない

実装は、SSLバージョン2.0互換のCLIENT-HELLOを 送信してはならない。 実装は、SSLバージョン2.0互換のCLIENT-HELLOを使用して、 TLS 1.3以降をネゴシエートしてはならない。 実装が、古いバージョンのTLSをネゴシエートするために SSLバージョン2.0互換のCLIENT-HELLOを受け入れることは 推奨されない

実装は、ClientHello.legacy_versionおよび ServerHello.legacy_versionに0x0303を 使用しなければならない。 その他のバージョン番号を持つHelloメッセージを受信した実装は、 第4.2.2節および第4.2.3節で説明されているように、 ハンドシェイクを中止しなければならない

実装は、0x0300未満のバージョンを持つレコードを 送信してはならない。 実装は、0x0300未満のバージョンを持つレコードを 受け入れないことが望ましい (ただし、レコードバージョン番号を完全に無視する場合、 意図せず受け入れることがある)。

実装は、[RFC6066]の第7節で 定義されるTruncated HMAC拡張を 使用してはならない。 この拡張はAEADアルゴリズムには適用できず、 一部のシナリオで安全でないことが示されているためである。

付録F. セキュリティ特性の 概要

TLSの完全なセキュリティ分析は本文書の範囲外である。 この付録では、望ましい特性を非形式的に説明するとともに、 より形式的な定義を提供する研究文献の詳細な研究への参照を示す。

ハンドシェイクの特性とレコード層の特性は、個別に扱う。

F.1. ハンドシェイク

TLSハンドシェイクは、片方向認証 (サーバーのみ)および相互認証 (クライアントとサーバー)の両方の機能を提供することを目的とした 認証付き鍵交換(AKE)プロトコルである。 ハンドシェイクが完了すると、各側は次の値についての自身の見解を出力する。

  • 一連の動作用鍵を導出できる 「セッション鍵」の集合 (main secretから導出されるさまざまな秘密)。 早期データを使用する場合は、 early secretからも秘密が導出されることに注意されたい。 これらの秘密は、以下で詳述するように、 main secretから導出されるものよりやや弱い特性を持つ。

  • 暗号パラメーター (アルゴリズムなど)の集合。

  • 通信当事者の識別情報。

攻撃者は能動的なネットワーク攻撃者、 すなわち当事者間の通信に使用されるネットワークを完全に制御できるものと仮定する [RFC3552]。 このような条件下でも、ハンドシェイクは以下に列挙する特性を提供することが望ましい。 これらの特性は必ずしも互いに独立しているとは限らないが、 プロトコル利用者のニーズを反映している。

同一のセッション鍵の確立:

各エンドポイントでハンドシェイクが正常に完了した場合、 ハンドシェイクは両側で同じセッション鍵の集合を出力する必要がある ([CK01]の定義1、第1部を参照)。

セッション鍵の秘密性:

共有セッション鍵は通信当事者だけが知るべきであり、 攻撃者に知られてはならない ([CK01]の定義1、第2部を参照)。 片方向認証された接続では、 攻撃者がサーバーとの間に独自のセッション鍵を確立できるが、 それらのセッション鍵はクライアントが確立したものとは異なることに注意されたい。

ピア認証:

ピア識別情報についてのクライアントの見解は、 サーバーの識別情報を反映すべきである。 クライアントが認証される場合、 ピア識別情報についてのサーバーの見解は、 クライアントの識別情報と一致すべきである。

セッション鍵の一意性:

異なる2つのハンドシェイクは、 異なる無関係なセッション鍵を生成すべきである。 ハンドシェイクによって生成される個々のセッション鍵も、 互いに異なり、独立しているべきである。

ダウングレード保護:

暗号パラメーターは両側で同一であり、 攻撃がない状態でピア同士が通信した場合と 同じであるべきである ([BBFGKZ16]の定義8および9を参照)。

長期鍵に関する前方秘匿性:

ハンドシェイク完了後に長期鍵素材 (この場合、証明書ベース認証モードの署名鍵、または 非対称鍵交換モードと組み合わせたPSKの外部/再開PSK)が侵害されても、 セッション鍵自体 (およびセッション鍵を再生成するために使用できるすべての素材)が 消去されている限り、セッション鍵のセキュリティは侵害されない ([DOW92]を参照)。 特に、鍵共有に対応する秘密鍵、共有秘密、および TLS鍵スケジュールで導出された鍵のうち、 binder_keyresumption_secret、および resumption_secretから導出されたPSK以外も消去する必要がある。 「psk_ke」PskKeyExchangeModeでPSKを使用する場合、 前方秘匿性は満たされない。 一時的または接続固有であることを意図した鍵や秘密を消去しないと、 実質的に、保護しなければならない追加の長期鍵が作成される。 これらの長期鍵が侵害されると (ハンドシェイク完了後であっても)、 接続トラフィックの保護が失われる可能性がある。

鍵侵害による偽装(KCI)への耐性:

証明書による相互認証接続では、 一方の主体の長期秘密が侵害されても、 指定された接続におけるその主体によるピア認証を破ってはならない ([HGFS15]を参照)。 例えば、クライアントの署名鍵が侵害されても、 後続のハンドシェイクで任意のサーバーをそのクライアントに対して 偽装できるようになるべきではない。

エンドポイント識別情報の保護:

サーバーの識別情報 (証明書)は受動的攻撃者から保護されるべきである。 クライアントの識別情報 (証明書)は、受動的攻撃者と能動的攻撃者の両方から保護されるべきである。 この特性は機密性を持たない暗号スイートでは成立しない。 本仕様ではそのような暗号スイートを定義しないが、 その他の文書で定義される場合がある。

非形式的には、TLS 1.3の署名ベースモードは、 非対称鍵交換によって確立され、 ハンドシェイクトランスクリプトに対するサーバーの署名によって認証され、 さらにMACによってサーバーの識別情報に結び付けられた、 一意で秘密の共有鍵を確立する。 クライアントが証明書によって認証される場合、 クライアントもハンドシェイクトランスクリプトに署名し、 両方の識別情報に結び付けられたMACを提供する。 [SIGMA]は、 この種類の鍵交換プロトコルの設計および分析を説明している。 接続ごとに新しい非対称鍵を使用する場合、 出力鍵は前方秘匿性を持つ。

外部PSKおよび再開PSKは、 長期共有秘密を起点として、 接続ごとに一意な短期セッション鍵の集合を生成する。 この秘密は以前のハンドシェイクで確立された可能性がある。 非対称鍵確立と組み合わせたPSKを使用する場合、 これらのセッション鍵も前方秘匿性を持つ。 再開PSKは、接続Nによって計算され、 接続N+1を形成するために必要な再開秘密が、 接続Nで使用されるトラフィック鍵とは分離されるよう設計されているため、 接続間の前方秘匿性を提供する。 さらに、同じ接続で複数のチケットが確立される場合、 それらは異なる鍵に関連付けられるため、 1つのチケットに関連付けられたPSKが侵害されても、 その他のチケットに関連付けられたPSKで確立された接続は侵害されない。 この特性は、チケットが自己暗号化される場合よりも、 データベースに保存され (したがって削除できる)場合に特に有用である。

前方秘匿性は、鍵漏えいの影響を一方向に制限する (時刻T2で鍵が侵害されても、T1 < T2である時刻T1の一部の鍵は侵害されない)。 逆方向の保護 (時刻T1での侵害が時刻T2の鍵を侵害しないこと)は、 非対称鍵確立を再実行することで実現できる。 長期認証鍵が侵害された場合、 非対称鍵確立を伴う完全なハンドシェイクは、 受動的攻撃者に対する保護を提供する。 resumption_secretが侵害された場合、 非対称鍵確立を伴う再開ハンドシェイクは、 受動的攻撃者に対する保護を提供し、 非対称鍵確立を伴う完全なハンドシェイクは、 能動的攻撃者に対する保護を提供する。 トラフィック秘密が侵害された場合、 非対称鍵確立を伴う任意のハンドシェイクが、 能動的攻撃者に対する保護を提供する。 [RFC7624]の用語を使用すると、 非対称鍵確立を再実行しない前方秘匿性では、 攻撃者による静的な鍵の持ち出しを阻止できない。 application_traffic_secret_Nが持ち出された後、 攻撃者は、例えば接続上で今後送信されるすべてのデータを受動的に盗聴できる。 これには、application_traffic_secret_N+1、 application_traffic_secret_N+2などで暗号化されたデータも含まれる。 非対称鍵確立を頻繁に再実行すると、 攻撃者は動的な鍵の持ち出し (またはコンテンツの持ち出し)を行う必要が生じる。

PSKバインダー値は、PSKと現在のハンドシェイクとの間、 およびPSKが確立されたセッション (NewSessionTicketメッセージによって確立された場合)と 現在のセッションとの間に結び付きを形成する。 元のハンドシェイクトランスクリプトは、 再開秘密を生成する値に取り込まれるため、 この結び付きには推移的に元のハンドシェイクトランスクリプトも含まれる。 これには、再開秘密を生成するために使用されるKDFと、 バインダーを計算するために使用されるMACの両方が 衝突耐性を持つことが必要である。 詳細については、付録F.1.1を参照されたい。 注: バインダーは、その他のPSKのバインダー値を対象としないが、 それらはFinished MACに含まれる。

注: 本仕様では現在、 非証明書ベースのハンドシェイク (例えばPSK)でサーバーがCertificateRequestメッセージを送信することを許可していない。 将来この制限が緩和された場合、 クライアントの署名はサーバーの証明書を直接対象としない。 ただし、PSKがNewSessionTicketによって確立された場合、 クライアントの署名はPSKバインダーを介して、 推移的にサーバーの証明書を対象とする。 [PSK-FINISHED]は、 サーバーの証明書に結び付けない構成に対する具体的な攻撃を説明している ([Kraw16]も参照)。 クライアントが2つの異なるエンドポイントと同じ PSK/key-idの組を共有する可能性がある場合、 証明書ベースのクライアント認証を使用することは安全でない。 これに反する別の仕様がない限り、 実装は外部PSKと、 クライアントまたはサーバーの証明書ベース認証を 組み合わせてはならない[RFC8773]は、 これを許可する拡張を提供するが、 本仕様と同等の水準の分析は受けていない。

エクスポーターを使用する場合、 一意のセッション鍵から生成されるため、 一意かつ秘密の値が生成される。 異なるラベルおよびコンテキストで計算されるエクスポーターは、 計算上独立しているため、 一方から他方を計算したり、 エクスポートされた値からセッション秘密を計算したりすることは現実的でない。 注: エクスポーターは任意長の値を生成できる。 エクスポーターをチャネルバインディングとして使用する場合、 エクスポートされる値は衝突耐性を提供するのに十分な大きさで なければならない。 TLS 1.3で提供されるエクスポーターは、 それぞれ早期トラフィック鍵およびアプリケーショントラフィック鍵と 同じHandshake Contextから導出されるため、 同様のセキュリティ特性を持つ。 これらにはクライアントの証明書が含まれないことに注意されたい。 クライアントの証明書に結び付けることを望む将来のアプリケーションは、 完全なハンドシェイクトランスクリプトを含む 新しいエクスポーターを定義する必要がある場合がある。

すべてのハンドシェイクモードで、 Finished MAC (および存在する場合は署名)がダウングレード攻撃を防止する。 さらに、第4.2.3節で説明されているように、 ランダムノンス内の特定のバイトを使用することで、 以前のTLSバージョンへのダウングレードを検出できる。 TLS 1.3およびダウングレードの詳細については、 [BBFGKZ16]を参照されたい。

クライアントとサーバーが共有鍵を確立するために十分な情報を 交換するとすぐに、ハンドシェイクの残りは暗号化されるため、 計算された共有鍵が認証されていない場合でも、 受動的攻撃者に対する保護を提供する。 サーバーはクライアントより先に認証するため、 クライアントは、サーバーに対して自身を認証する場合、 認証済みのサーバーにだけ識別情報を公開することを保証できる。 実装は、長さによって識別情報に関する情報が漏えいすることを回避するため、 ハンドシェイク中に提供されたレコードパディング機構を使用しなければならないことに注意されたい。 クライアントが提示するPSK識別情報も、 サーバーが選択する識別情報も暗号化されない。

F.1.1. 鍵導出および HKDF

TLS 1.3の鍵導出では、 [RFC5869]で定義されるHKDFと、 その2つの構成要素であるHKDF-ExtractおよびHKDF-Expandを使用する。 HKDF構成の完全な根拠は[Kraw10]に、 TLS 1.3での使用方法の根拠は[KW16]に記載されている。 本文書全体で、HKDF-Extractの各適用の後には、 HKDF-Expandの1回以上の呼び出しが続く。 この順序は常に従うことが望ましい (本文書の将来の改訂を含む)。 特に、間にHKDF-Expandを挟まずに、 HKDF-Extractの出力を別のHKDF-Extractの入力として 使用しないことが望ましい。 鍵および/またはラベルによって区別される限り、 同じ入力の一部に対してHKDF-Expandを複数回適用することは許可される。

HKDF-Expandは、 入力と出力の両方が可変長の疑似乱数関数 (PRF)を実装することに注意されたい。 本文書におけるHKDFの一部の用途 (例えば、エクスポーターおよびresumption_secretの生成)では、 HKDF-Expandの適用が衝突耐性を持つ必要がある。 すなわち、同じ値を出力する HKDF-Expandへの異なる2つの入力を見つけることが 現実的であってはならない。 これには、基礎となるハッシュ関数が衝突耐性を持ち、 HKDF-Expandの出力長が少なくとも256ビット (またはハッシュ関数で衝突を見つけることを防ぐために必要な長さ) であることが必要である。

F.1.2. 証明書ベースのクライアント認証

ハンドシェイク中またはハンドシェイク後認証で、 証明書ベースの認証データをサーバーに送信したクライアントは、 その後サーバーがクライアントを認証済みと見なすかどうかを確認できない。 サーバーが接続を片方向認証または相互認証のいずれと見なしているかを クライアントが判定する必要がある場合、 これはアプリケーション層によって提供されなければならない。 詳細については[CHHSV17]を参照されたい。 さらに、[Kraw16]による ハンドシェイク後認証の分析は、 ハンドシェイク後の段階で送信された証明書によって識別されるクライアントが トラフィック鍵を保持していることを示している。 したがって、この当事者は、 元のハンドシェイクに参加したクライアント、 または元のクライアントからトラフィック鍵を委任された者である (トラフィック鍵が侵害されていないものとする)。

F.1.3. 0-RTT

0-RTT動作モードは一般に、 1-RTTデータと同様のセキュリティ特性を提供するが、 2つの例外がある。 0-RTT暗号化鍵は完全な前方秘匿性を提供せず、 また、サーバーは潜在的に過大な量の状態を保持しない限り、 ハンドシェイクの一意性 (リプレイ不可能性)を保証できない。 リプレイへの露出を制限する機構については、 第8節を参照されたい。

F.1.4. エクスポーターの 独立性

exporter_secretおよびearly_exporter_secretは、 トラフィック鍵から独立するよう導出されるため、 それらの鍵で暗号化されたトラフィックのセキュリティを脅かさない。 ただし、これらの秘密は任意のエクスポーター値を計算するために使用できるため、 可能な限り早く消去することが 望ましい。 エクスポーターラベルの全集合が既知である場合、 実装は、それらすべてのラベルについて エクスポーター計算の内部Derive-Secret段階を事前計算し、 その後[early_]exporter_secretを消去し、 各内部値も今後不要であることが分かり次第、 消去することが望ましい

F.1.5. 侵害後 セキュリティ

TLSは、ピアの長期秘密 (署名鍵または外部PSK)が侵害された後に行われる ハンドシェイクのセキュリティを提供しない。 したがって、侵害後セキュリティ [CCG16]を提供しない。 これは後方秘匿性または将来秘匿性と呼ばれることもある。 これは、一方の当事者自身の長期秘密が侵害された後に その当事者が持つセキュリティ保証を説明する KCI耐性とは異なる。

F.1.6. 外部 参考文献

TLSハンドシェイクの分析については、 次の参考文献を参照されたい: [DFGS15][CHSV16][DFGS16][KW16][Kraw16][FGSW16][LXZFH16][FG17]、および[BBK17]

F.2. レコード層

レコード層は、 双方向の暗号化鍵およびノンスを導出するために使用できる、 強力なトラフィック秘密をハンドシェイクが生成することに依存する。 それが成立し、鍵が第5.5節で示される量を 超えるデータに使用されないと仮定すると、 レコード層は次の保証を提供することが望ましい。

機密性:

攻撃者は、指定されたレコードの 平文内容を判定できないことが望ましい。

完全性:

攻撃者は、既存のレコードとは異なるが、 受信者に受け入れられる新しいレコードを作成できないことが望ましい。

順序保護/リプレイ不可能性:

攻撃者は、受信者がすでに受け入れたレコードを 再び受け入れさせたり、 レコードNを先に処理せずにレコードN+1を 受け入れさせたりできないことが望ましい。

長さの秘匿:

指定された外部長を持つレコードについて、 攻撃者はレコードのうちコンテンツとパディングが それぞれどれだけを占めるか判定できないことが望ましい。

鍵変更後の前方秘匿性:

第4.7.3節で説明される トラフィック鍵更新機構が使用され、 前世代の鍵が削除された場合、 エンドポイントを侵害した攻撃者は、 古い鍵で暗号化されたトラフィックを復号できないことが望ましい。

非形式的には、TLS 1.3は、 強力な鍵で平文をAEAD保護することでこれらの特性を提供する。 AEAD暗号化[RFC5116]は、 データの機密性および完全性を提供する。 リプレイ不可能性は、各レコードに異なるノンスを使用し、 ノンスをレコードシーケンス番号 (第5.3節)から導出することで提供される。 シーケンス番号は両側で独立して維持されるため、 順序が入れ替わって配送されたレコードは、 AEAD保護解除に失敗する。 同じ平文が異なる利用者によって同じ鍵で繰り返し暗号化される場合 (HTTPでは一般的)に大量暗号解析を防止するため、 ノンスは、シーケンス番号と、 トラフィック鍵とともに導出される接続ごとの秘密初期化ベクトルを 混合することで形成される。 この構成の分析については、[BT16]を参照されたい。

TLS 1.3の再鍵付け技法 (第7.2節を参照)は、 [REKEY]で論じられる直列生成器の構成に従っている。 同文献は、再鍵付けによって、 再鍵付けを行わない場合より多くの暗号化に鍵を使用できることを示している。 これは、疑似乱数関数 (PRF)としてのHKDF-Expand-Label関数のセキュリティに依存する。 さらに、この関数が真に一方向である限り、 鍵変更前のトラフィック鍵を計算することは不可能である (前方秘匿性)。

TLSは、接続のトラフィック秘密が侵害された後に、 その接続上で通信されるデータのセキュリティを提供しない。 すなわち、TLSはトラフィック秘密に関する 侵害後セキュリティ/将来秘匿性/後方秘匿性を提供しない。 実際、トラフィック秘密を知った攻撃者は、 その接続上の将来のすべてのトラフィック秘密を計算できる。 そのような保証を必要とするシステムは、 新しいハンドシェイクを行い、 非対称鍵交換を使用する新しい接続を確立する必要がある。

F.2.1. 外部 参考文献

TLSレコード層の分析については、 次の参考文献を参照されたい: [BMMRT15][BT16][BDFKPPRSZZ16][BBK17]、および[PS18]

F.3. トラフィック分析

TLSは、暗号化されたパケットの長さおよびタイミングを観測することに 基づく、さまざまなトラフィック分析攻撃に対して脆弱である [CLINIC] [HCJC16]。 固定されたコンテンツ群をホストする動画サーバーなど、 区別すべき可能なメッセージの集合が小さい場合には特に容易であるが、 より複雑なシナリオでも有用な情報を提供する。

TLSは、この形式の攻撃に対する特定の防御策を提供しないが、 アプリケーションが使用するためのパディング機構を含む。 AEAD関数によって保護される平文は、 コンテンツと可変長パディングから構成されるため、 アプリケーションは任意長の暗号化レコードを生成でき、 また送信期間と無通信期間の違いを隠すため、 パディングだけからなるカバートラフィックを生成できる。 パディングは実際のコンテンツとともに暗号化されるため、 攻撃者はパディングの長さを直接判定できない。 ただし、レコード処理中に公開されるタイミングチャネルを使用して、 間接的に測定できる場合がある (例えば、レコードの処理時間を確認したり、 レコードを少しずつ送信して、どのレコードがサーバーからの応答を引き起こすかを確認したりする)。 一般に、定時間のパディング除去関数であっても、 コンテンツをデータ依存関数に渡す可能性が高いため、 これらのチャネルをすべて除去する方法は分かっていない。 最低限、完全に定時間で動作するサーバーまたはクライアントには、 上位レベルプロトコルも定時間にすることを含め、 アプリケーション層プロトコル実装との緊密な協調が必要になる。

注: 堅牢なトラフィック分析防御策は、 パケット送信の遅延およびトラフィック量の増加により、 性能を低下させる可能性が高い。

F.4. サイドチャネル攻撃

一般に、TLSはサイドチャネル攻撃 (すなわち、タイミングなどの二次的なチャネルを介して通信を攻撃するもの) に対する特定の防御策を持たず、 関連する暗号プリミティブの実装に委ねている。 ただし、TLSの一部の機能は、 サイドチャネル耐性を持つコードを記述しやすくするよう設計されている。

  • 複合的なMAC-then-encrypt構造を使用していた 以前のバージョンのTLSとは異なり、 TLS 1.3はAEADアルゴリズムだけを使用するため、 実装はこれらのプリミティブの自己完結型定時間実装を使用できる。

  • TLSは、すべての復号エラーに対して 一様な「bad_record_mac」アラートを使用する。 これは、攻撃者がメッセージの一部について段階的な情報を得ることを 防ぐことを意図している。 このようなエラーで接続を終了することにより、 追加の耐性が提供される。 新しい接続では暗号素材が異なるため、 複数回の試行を必要とする暗号プリミティブへの攻撃が防止される。

サイドチャネルによる情報漏えいは、 TLSより上位の層、すなわちアプリケーションプロトコルおよび それを使用するアプリケーションでも発生する可能性がある。 サイドチャネル攻撃への耐性は、 アプリケーションおよびアプリケーションプロトコルがそれぞれ、 機密情報を意図せず漏えいしないことを保証することに依存する。

F.5. 0-RTTへの リプレイ攻撃

リプレイ可能な0-RTTデータは、 TLSを使用するアプリケーションがリプレイに対して安全となるよう 明示的に設計されていない限り、 それらのアプリケーションに多数のセキュリティ上の脅威をもたらす (最低限、これは冪等であることを意味するが、 多くの場合、定時間応答など、その他のより強い条件も必要になる場合がある)。 潜在的な攻撃には次が含まれる。

  • 副作用を引き起こす操作 (例えば、商品の購入や送金)を複製し、 サイトまたは利用者に損害を与える。

  • 攻撃者は0-RTTメッセージを保存およびリプレイし、 その他のメッセージとの相対的な順序を変更できる (例えば、削除を作成の後へ移動する)。

  • キャッシュなどの副作用によって引き起こされる 既存の情報漏えいを増幅する。 攻撃者は、関心のあるリソースをまだキャッシュしていない キャッシュノードに0-RTTメッセージをリプレイし、 別の接続を使用してそのリソースがキャッシュに追加されたかどうか確認することで、 0-RTTメッセージの内容に関する情報を得られる可能性がある。 これは、0-RTTメッセージをリプレイできる限り、 異なるキャッシュノードで繰り返すことができる。

データを多数回リプレイできる場合、 暗号処理の速度を繰り返し測定するなど、 追加の攻撃が可能になる。 さらに、レート制限システムを過負荷にできる可能性がある。 これらの攻撃の詳細については、[Mac17]を参照されたい。

最終的に、0-RTTデータの複製を使用する攻撃から 自身を保護する責任はサーバーにある。 第8節で説明される機構は、 TLS層でのリプレイを防止することを目的としているが、 クライアントデータの複数の複製を受信することに対する 完全な保護は提供しない。 TLS 1.3は、サーバーがクライアントに関する情報を持たない場合、 1-RTTハンドシェイクにフォールバックする。 例えば、状態を共有しない別のクラスターにある場合や、 第8.1節で説明されるように チケットが削除された場合である。 この状況でアプリケーション層プロトコルがデータを再送信すると、 攻撃者はClientHelloを元のクラスター (データを直ちに処理する)と、 1-RTTへフォールバックし、 アプリケーション層のリプレイ時にデータを処理する別のクラスターの両方へ送信することで、 メッセージの複製を引き起こせる可能性がある。 この攻撃の規模は、クライアントがトランザクションを再試行する意思によって制限されるため、 限られた量の複製だけが可能であり、 各複製はサーバーにとって新しい接続として現れる。

正しく実装された場合、 第8.1節および第8.2節で説明される機構は、 リプレイされたClientHelloおよび関連する0-RTTデータが、 一貫した状態を持つ任意のクラスターによって複数回受け入れられることを防止する。 単一のチケットについて0-RTTの使用を1つのクラスターに制限するサーバーでは、 指定されたClientHelloおよび関連する0-RTTデータは1回だけ受け入れられる。 ただし、状態が完全には一貫していない場合、 攻撃者がレプリケーション時間枠中に データの複数の複製を受け入れさせられる可能性がある。 クライアントはサーバー動作の正確な詳細を把握できないため、 リプレイされても安全でなく、 複数の1-RTT接続で再試行する意思のないメッセージを 早期データで送信してはならない

アプリケーションプロトコルは、 その使用を定義するプロファイルなしで0-RTTデータを 使用してはならない。 そのプロファイルは、0-RTTで安全に使用できるメッセージまたは対話と、 サーバーが0-RTTを拒否して1-RTTへフォールバックする場合の処理方法を 識別する必要がある。

さらに、偶発的な誤用を回避するため、 TLS実装は、アプリケーションから明示的に要求されない限り、 0-RTT (送信または受け入れのいずれも)を 有効にしてはならず、 サーバーに拒否された0-RTTデータを、 アプリケーションから指示されない限り自動的に 再送信してはならない。 サーバー側アプリケーションは、 一部の種類のアプリケーショントラフィックについて、 0-RTTデータの特別な処理を実装することを望む場合がある (例えば、接続を中止する、 アプリケーション層でデータを再送信するよう要求する、 またはハンドシェイクが完了するまで処理を遅延する)。 アプリケーションがこの種類の処理を実装できるようにするため、 TLS実装は、ハンドシェイクが完了したかどうかを アプリケーションが判定できる方法を 提供しなければならない

F.5.1. リプレイおよび エクスポーター

ClientHelloをリプレイすると、 同じ早期エクスポーターが生成されるため、 これらのエクスポーターを使用するアプリケーションには追加の注意が必要である。 特に、これらのエクスポーターを認証チャネルバインディングとして使用する場合 (例えば、エクスポーターの出力に署名する場合)、 PSKを侵害した攻撃者は、 認証鍵を侵害せずに接続間で認証子を移植できる。

さらに、早期エクスポーターを使用して、 サーバーからクライアントへの暗号化鍵を生成 しないことが望ましい。 その場合、それらの鍵が再利用されることになるためである。 これは、早期アプリケーショントラフィック鍵が クライアントからサーバーへの方向だけで使用されることと対応している。

F.6. PSK識別情報の露出

実装は無効なPSKバインダーに対して ハンドシェイクを中止することで応答するため、 攻撃者が指定されたPSK識別情報が有効かどうかを 検証できる可能性がある。 具体的には、サーバーが外部PSKおよび証明書ベースの 両方のハンドシェイクを受け入れる場合、 有効なPSK識別情報ではハンドシェイクが失敗する一方、 無効な識別情報は単に読み飛ばされ、 証明書ハンドシェイクが成功する。 PSKハンドシェイクだけをサポートするサーバーは、 有効なPSK識別情報が存在しない場合と、 識別情報は存在するがバインダーが無効な場合を 同じように扱うことで、この形式の攻撃に耐えられる可能性がある。

F.7. プロトコルバージョン間での PSK共有

TLS 1.3は、PSKを特定のKDFに結び付けるという 保守的な方法を採用している。 これに対し、TLS 1.2では、 任意のハッシュ関数およびTLS 1.2 PRFとともにPSKを使用できる。 したがって、TLS 1.2とTLS 1.3の両方で使用されるPSKは、 TLS 1.3では1つのハッシュだけとともに使用しなければならず、 利用者が単一のPSKをプロビジョニングしたい場合には最適とは言えない。 TLS 1.2とTLS 1.3の構成は、 いずれもHMACに基づいているが異なる。 同じPSKが両方のバージョンで関連する出力を生成する既知の方法はないが、 行われた分析は限定的である。 実装は、TLS 1.3とTLS 1.2の間でPSKを再利用しないことで、 クロスプロトコルの関連出力に対する安全性を保証できる。

F.8. 外部PSKおよび 再ルーティング

TLSの外部PSKは、 正確に1つのクライアントと1つのサーバーだけが知るよう設計されている。 ただし、[RFC9257]で述べられているように、 PSKを3つ以上のエンティティで共有する使用例がある。 このようなシナリオでは、 侵害されたグループメンバーがその他の任意のメンバーを偽装できるという 予想されるセキュリティ上の弱点に加えて、 悪意のある非メンバーが、 正直なグループメンバー間のハンドシェイクを再ルーティングし、 意図しない方法で接続させられる [Selfie][RFC9257]は、 [RFC9258]で定義される 外部PSKインポーターの使用を含め、 このような悪意のあるメッセージの再ルーティングを防止する 外部PSK使用の推奨事項を提供する。

F.9. 自己署名証明書または 生の公開鍵を使用する場合の誤結合

TLS 1.3を、有用な識別情報を持たない自己署名証明書 (DTLS-SRTP [RFC5763]など) またはピア認証用の生の公開鍵 [RFC7250]とともに使用する場合、 誤結合攻撃[MM24]に対して 脆弱になる可能性がある。 このリスクは、「external_id_hash」拡張 [RFC8844]を使用するか、 サーバーだけを認証する場合には、 「server_name」拡張が想定される識別情報と一致することを サーバーが検証することで軽減できる。

F.10. 静的RSAへの攻撃

TLS 1.3はRSA鍵トランスポートを使用しないため、 Bleichenbacher型の攻撃[Blei98]に直接脆弱ではない。 ただし、TLS 1.3サーバーが以前のバージョンのTLSで 静的RSAもサポートする場合、 TLS 1.3接続に対してサーバーを偽装できる可能性がある [JSS15]。 TLS 1.3実装は、すべてのTLSバージョンで静的RSAのサポートを 無効にすることでこの攻撃を防止できる。 原理上、実装は、静的RSA復号用とRSA署名用に 異なるkeyUsageビットを持つ証明書を分離できる可能性もある。 ただし、この技法は、 digitalSignatureビットが設定されていない証明書内の鍵による署名を、 クライアントが受け入れないことに依存し、 多くのクライアントはこの制限を強制しない。

貢献者

Martin Abadi
カリフォルニア大学サンタクルーズ校
abadi@cs.ucsc.edu

Christopher Allen
(TLS 1.0の共同編集者)
Alacrity Ventures
ChristopherA@AlacrityManagement.com

Nimrod Aviram
テルアビブ大学
nimrod.aviram@gmail.com

Richard Barnes
Cisco
rlb@ipv.sx

Steven M. Bellovin
コロンビア大学
smb@cs.columbia.edu

David Benjamin
Google
davidben@google.com

Benjamin Beurdouche
INRIA & Microsoft Research
benjamin.beurdouche@ens.fr

Karthikeyan Bhargavan
(RFC 7627の編集者)
INRIA
karthikeyan.bhargavan@inria.fr

Simon Blake-Wilson
(RFC 4492の共同著者)
BCI
sblakewilson@bcisse.com

Nelson Bolyard
(RFC 4492の共同著者)
Sun Microsystems, Inc.
nelson@bolyard.com

Ran Canetti
IBM
canetti@watson.ibm.com

Matt Caswell
OpenSSL
matt@openssl.org

Stephen Checkoway
イリノイ大学シカゴ校
sfc@uic.edu

Pete Chown
Skygate Technology Ltd
pc@skygate.co.uk

Katriel Cohn-Gordon
オックスフォード大学
me@katriel.co.uk

Cas Cremers
オックスフォード大学
cas.cremers@cs.ox.ac.uk

Antoine Delignat-Lavaud
(RFC 7627の共同著者)
INRIA
antdl@microsoft.com

Tim Dierks
(TLS 1.0の共同著者、TLS 1.1および1.2の共同編集者)
独立系
tim@dierks.org

Roelof DuToit
Symantec Corporation
roelof_dutoit@symantec.com

Taher Elgamal
Securify
taher@securify.com

Pasi Eronen
Nokia
pasi.eronen@nokia.com

Cedric Fournet
Microsoft
fournet@microsoft.com

Anil Gangolli
anil@busybuddha.org

David M. Garrett
dave@nulldereference.com

Illya Gerasymchuk
独立系
illya@iluxonchik.me

Alessandro Ghedini
Cloudflare Inc.
alessandro@cloudflare.com

Daniel Kahn Gillmor
ACLU
dkg@fifthhorseman.net

Matthew Green
ジョンズ・ホプキンス大学
mgreen@cs.jhu.edu

Jens Guballa
ETAS
jens.guballa@etas.com

Felix Guenther
ダルムシュタット工科大学
mail@felixguenther.info

Vipul Gupta
(RFC 4492の共同著者)
Sun Microsystems Laboratories
vipul.gupta@sun.com

Chris Hawk
(RFC 4492の共同著者)
Corriente Networks LLC
chris@corriente.net

Kipp Hickman

Alfred Hoenes

David Hopwood
独立コンサルタント
david.hopwood@blueyonder.co.uk

Marko Horvat
MPI-SWS
mhorvat@mpi-sws.org

Jonathan Hoyland
ロンドン大学ロイヤル・ホロウェイ
jonathan.hoyland@gmail.com

Subodh Iyengar
Facebook
subodh@fb.com

Benjamin Kaduk
Akamai Technologies
kaduk@mit.edu

Hubert Kario
Red Hat Inc.
hkario@redhat.com

Phil Karlton
(SSL 3.0の共同著者)

Leon Klingele
独立系
mail@leonklingele.de

Paul Kocher
(SSL 3.0の共同著者)
Cryptography Research
paul@cryptography.com

Hugo Krawczyk
IBM
hugokraw@us.ibm.com

Adam Langley
(RFC 7627の共同著者)
Google
agl@google.com

Olivier Levillain
ANSSI
olivier.levillain@ssi.gouv.fr

Xiaoyin Liu
ノースカロライナ大学チャペルヒル校
xiaoyin.l@outlook.com

Ilari Liusvaara
独立系
ilariliusvaara@welho.com

Atul Luykx
ルーヴェン・カトリック大学
atul.luykx@kuleuven.be

Colm MacCarthaigh
Amazon Web Services
colm@allcosts.net

Carl Mehner
USAA
carl.mehner@usaa.com

Jan Mikkelsen
Transactionware
janm@transactionware.com

Bodo Moeller
(RFC 4492の共同著者)
Google
bodo@acm.org

Kyle Nekritz
Facebook
knekritz@fb.com

Erik Nygren
Akamai Technologies
erik+ietf@nygren.org

Magnus Nystrom
Microsoft
mnystrom@microsoft.com

Kazuho Oku
株式会社ディー・エヌ・エー
kazuhooku@gmail.com

Kenny Paterson
ロンドン大学ロイヤル・ホロウェイ
kenny.paterson@rhul.ac.uk

Christopher Patton
フロリダ大学
cjpatton@ufl.edu

Alfredo Pironti
(RFC 7627の共同著者)
INRIA
alfredo.pironti@inria.fr

Andrei Popov
Microsoft
andrei.popov@microsoft.com

John Preuß Mattsson
Ericsson
john.mattsson@ericsson.com

Marsh Ray
(RFC 7627の共同著者)
Microsoft
maray@microsoft.com

Robert Relyea
Netscape Communications
relyea@netscape.com

Kyle Rose
Akamai Technologies
krose@krose.org

Jim Roskind
Amazon
jroskind@amazon.com

Michael Sabin

Joe Salowey
Tableau Software
joe@salowey.net

Rich Salz
Akamai
rsalz@akamai.com

David Schinazi
Apple Inc.
dschinazi@apple.com

Sam Scott
ロンドン大学ロイヤル・ホロウェイ
me@samjs.co.uk

Mohit Sethi
アールト大学
mohit@iki.fi

Thomas Shrimpton
フロリダ大学
teshrim@ufl.edu

Dan Simon
Microsoft, Inc.
dansimon@microsoft.com

Brian Smith
独立系
brian@briansmith.org

Ben Smyth
Ampersand
www.bensmyth.com

Brian Sniffen
Akamai Technologies
ietf@bts.evenmere.org

Nick Sullivan
Cloudflare Inc.
nick@cloudflare.com

Bjoern Tackmann
カリフォルニア大学サンディエゴ校
btackmann@eng.ucsd.edu

Tim Taubert
Mozilla
ttaubert@mozilla.com

Martin Thomson
Mozilla
mt@mozilla.com

Hannes Tschofenig
Arm Limited
Hannes.Tschofenig@arm.com

Sean Turner
sn3rd
sean@sn3rd.com

Steven Valdez
Google
svaldez@google.com

Filippo Valsorda
Cloudflare Inc.
filippo@cloudflare.com

Thyla van der Merwe
ロンドン大学ロイヤル・ホロウェイ
tjvdmerwe@gmail.com

Victor Vasiliev
Google
vasilvv@google.com

Loganaden Velvindron
cyberstorm.mu
logan@cyberstorm.mu

Hoeteck Wee
パリ高等師範学校
hoeteck@alum.mit.edu

Tom Weinstein

David Wong
NCC Group
david.wong@nccgroup.trust

Christopher A. Wood
Apple Inc.
cawood@apple.com

Tim Wright
Vodafone
timothy.wright@vodafone.com

Peter Wu
独立系
peter@lekensteyn.nl

Kazu Yamamoto
株式会社インターネットイニシアティブ
kazu@iij.ad.jp

著者の連絡先

Eric Rescorla
独立系