6 <- index ->8


7. TLS ハンドシェイク関連プロトコル English

TLS は、3 つのサブプロトコルをもつ。これは、ピアがレコード層用のセキュリティパラメータについて合意できるようにするため、ピア自体を認証(authenticate)できるようにするため、交渉されたセキュリティパラメータを開始するため、そして、エラー条件を相互に報告するために使われる。

ハンドシェイクプロトコルは、下記の要素から成るセッションの交渉を担う。:

セッション識別子(session identifier)
 

活動中の(active)もしくは再利用可能なセッション状態を識別するために、サーバによって選択された任意のバイト列( byte sequence)。


ピア証明書(peer certificate)
  そのピアの X509v3 [PKIX] 証明書。その状態の、この要素は、null である可能性がある。

圧縮手法(compression method)
  データを 暗号化の前に圧縮するために使われるアルゴリズム。

cipher spec
 

鍵とする素材を生成するために使われる PRF(pseudorandom function)。バルクデータ暗号化アルゴリズム(例: null、AES 等)および MAC アルゴリズム(例: HMAC-SHA1)を規定する。これは、mac_length のような暗号技術的属性も規定する。(公式な定義については Appendix A.6 を参照。)

master secret
  クライアントとサーバ間で共有される 48 byte の secret。

is resumable
  「そのセッションは、新しいコネクションを開始するために使えるか否か?」を示すフラグ。

そして、これらの要素は、アプリケーションデータを防護するとき、レコード層によって用されるセキュリティパラメータを作るために使われる。多くのコネクションは、TLS ハンドシェイクプロトコルの失敗の再開を通じて同一セッションを使って具体化される可能性がある。

7.1. Change Cipher Spec プロトコル English

Change cipher Spec プロトコルは、暗号(ciphering)戦略における変更(transition)を知らせるために存在する。このプロトコルは、現在の(pending ではない)コネクション状態のもとで暗号化され、圧縮された単一のメッセージから成る。このメッセージは、値が 1 の 1byte から成る。

   struct {
       enum { change_cipher_spec(1), (255) } type;
   } ChangeCipherSpec;

ChangeCipherSpec メッセージは、そのクライアントおよびサーバの両方によって、その受信者に「以降のレコードは、新しく交渉される CipherSpec および鍵のもとで保護されること」を通知するために送られる。このメッセージの受領は、その受信者に、レコード層に read pending の状態を read 現在の状態に、ただちにコピーすることを指図することをもたらす。このメッセージを送った直後に、その送信者は、レコード層に write pending 状態を write active 状態にすることを指図しなければならない(MUST)。(6.1 節を参照。) TChangeCipherSpec メッセージは、そのセキュリティパラメータが合意された後、そのハンドシェイクの間に(ただし、その verifying Finished メッセージが送られる前に)送られる。

注:
再ハンドシェイクが、データがあるコネクション上を流れている過程で起きる場合、その通信を行う主体は、その古い CipherSpec を使ってデータを送り続ける可能性がある。しかし、ひとたび、その ChangeCipherSpec が送られるたら、その新しい CipherSpec が使われなければならない(MUST) 。ChangeCipherSpec を最初に送る側は、「他方の側は、新しい鍵とする素材の計算を完了したこと」を知らない(例: それが、時間を費やす公開鍵の操作を行う必要がある場合)。それゆえ、その受信者がデータを貯めなければならない間の短時間、存在する可能性がある(MAY)。現代のマシンを使う実務において、この間隔は、概ね短い可能性が高い。

7.2. アラートプロトコル English

TLS レコード層によってサポートされるコンテンツ種別のひとつは、アラートタイプである。アラートメッセージは、そのメッセージの深刻さ(severity)(warning もしくは fatal)および、そのアラートについての記述を運ぶ。fatal レベルのアラートメッセージは、そのコネクションの中断( immediate termination)をもたらす。この場合、そのセッションに対応する他のコネクションは、続く可能性があるが、そのセッション識別子は、無効とし、その失敗したセッションを、新しいコネクションを確立するために使われることから防がなければならない(MUST)。他のメッセージと同様に、アラートメッセージは、現在のコネクション状態によって規定されているように暗号化され、圧縮される。

   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(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),
       user_canceled(90),
       no_renegotiation(100),
       unsupported_extension(110),
       (255)
   } AlertDescription;
   struct {
       AlertLevel level;
       AlertDescription description;
   } Alert;
7.2.1. Closure アラート English

クライアントおよびそのサーバは、「そのコネクションは、truncation 攻撃を避けるために終了する」という知識を共有しなければならない。いずれの主体も、closing メッセージの交換を開始する可能性がある。

close_notify
 

このメッセージは、「その送信者は、これ以上、このコネクション上のメッセージを送らないこと」 を、その受信者宛に通知する。 「TLS 1.1 においては、 コネクションを正しく閉じることの失敗は、もはや、セッションが中断(resume)されないことを要求しないこと」に注意。これは、広範な実装実践を確保するための TLS 1.0 からの変更点である。

両者は、close_notify アラートを送ることによって閉鎖を開始する可能性がある。closure アラートの後、受け取られた、いかなるデータ も、無視される。

何らかの他の fatal アラートが転送されていない限り、各主体には、close_notify アラートを、そのコネクションの write 側を閉じる前に送ることが要求される。他方の主体は、自身の close_notify アラートで応答し、(あらゆる pending writes を棄却して、)そのコネクションをただちに閉じなければならない(MUST)。その close の開始者には、そのコネクションの read side を閉じる前に対応する close_notify アラートを待つことは、要求されない。

TLS を使っているアプリケーションプロトコルについて、TLS コネクションが閉じた後に、あらゆるデータが下層のトランスポート上を運ばれる可能性があるとする場合、TLS 実装は、アプリケーション層宛に「その TLS コネクションは、終端したこと」を示す前に、対応する close_notify アラート を受け取らなければならない。そのアプリケーションプロトコルが、いかなる追加的なデータも転送しないが、その下層のトランスポート コネクションを閉じるのみの場合、その実装は、対応する close_notify を待つこと無しに、そのトランスポートを閉じることを選択する可能性がある(MAY)。この標準には、(「いつ、コネクションは、開けられるか、あるいは、閉じられるか?」を含めて) TLS についての用法プロファイルがそのデータのトランスポートを管理するような作法を命令していると受け止める必要がある箇所は無い。

注: 「トランスポートを壊す(destroying)前に、pending データを信頼性をもって配信するコネクションを閉じること」が想定されている。

7.2.2. エラーアラート English

TLS ハンドシェイクプロトコルにおけるエラーハンドリングは、とてもシンプルである。あるエラーが検知されたとき、検知者は、メッセージを他方宛に送る。
fatal アラートメッセージの転送(transmission)もしくは受領(receipt)の際、両者は、すぐに、そのコネクションを閉じる。サーバおよびクライアントは、いかなるセッション識別子、鍵、および、failed コネクションに関連する secret も忘れなければならない(MUST)。それゆえ、fatal アラートによって終了された、いかなるコネクションも、中断(resume)されてはならない(MUST NOT)

ある実装が fatal アラートとして定義されている条件に遭遇するときはいつも、それは、適切なアラートを、そのコネクションを閉じる前に送らなければならない(MUST)。アラートレベルが明示的に規定されていない、すべてのエラーについて、送信者は、その自由裁量において、「これを fatal エラーとして扱うか否か?」を判定する可能性がある(MAY)。その実装が、アラートを送るが、その後、ただちにコネクションを閉じることを意図することを選択する場合、それは、そのアラートを fatal アラートレベルとして送らなければならない(MUST)

警告(warning)レベルのアラートが送受信される場合、一般に、そのコネクションは、普通に続行できる。その受信者が、そのコネクションについては続けないと判断する場合 (例: 受容することを望んでいない再交渉(renegotiation)アラートを受信しなかった後)、それは、そのコネクションを切断するために、fatal アラートを送る必要がある(SHOULD)。これが与えられると、その送信者は、一般に、「どのように、その受信者は、ふるまうか?」を知ることができない。それゆえ、警告アラートは、その送信者が、そのコネクションを続けることを望むとき、さほど有用ではなく、それゆえ、しばしば省略される。例えば、あるピアが、(おそらく、これを、そのユーザと共に確認した後)期限が切れた証明書を許容することを判断し、そのコネクションを継続することを望む場合、これは、一般的には、certificate_expired アラートを送らない。

下記のエラーアラートが定義されている。:

unexpected_message
  不適切なメッセージが受信された。このアラートは、常に、fatal であり、決して正規の実装間の通信において観察されないようにする必要がある。

bad_record_mac
 

このアラートは、ある record が誤った MAC と共に受信される場合、返される。このアラートは、TLSCiphertext が不適(invalid)な様に復号されたことに起因してアラートが送られる場合にも返されなければならない(MUST)。:(これがそのブロック長の倍数でさえなかったか、あるいは、チェックされるとき、その padding 値は不正であったか、のいずれか。)このメッセージは、常に fatal であり、(メッセージが、そのネットワークにおいて壊されていたときを除いて)正しい実装間の通信において、決して観測されないようにする必要がある。


decryption_failed_RESERVED
  このアラートは、TLS のいくつかの以前のバーションにおいて使われてきた。そして、CBC mode [CBCATT] に対する特定の攻撃許容していた可能性がある。これは、準拠実装によって送られてはならない(MUST NOT)

record_overflow
 

TLSCiphertext レコードが、受信され、それが 2^14+2048 byte より長い長さをもつ。あるいは、あるレコードが 2^14+1024 byte より長い長さをもつ TLSCompressed レコードに復号された。このメッセージは、常に fatal であり、正しい実装間の通信において(メッセージがネットワーク中で壊されたときを除いて)決して観察されないようにする必要がある。


decompression_failure
 

解凍(decompression)関数が、不正な input を受信した(例: 過剰な長さに拡張するデータ )。このメッセージは、常に fatal であり、正規の(proper)実装間の通信において決して観測されないようにする必要がある。


handshake_failure
 

handshake_failure アラートメッセージの受領は、「その送信者は、オプションが利用可能としたら、許容可能なセキュリティパラメータの集合を交渉できなかったこと」を示す。これは、fatal エラーである。


no_証明書_RESERVED
  このアラートは、SSLv3 において使われていたが、いかなるバーションの TLS においても使われていない。これは、準拠実装によって送られてはならない(MUST NOT)

bad_certificate
 

証明書が壊れていた、正しく検証しなかった署名を収めていた等。


unsupported_certificate
  証明書は、サポートされていない種別のものであった。

certificate_revoked
  証明書は、その署名者によって失効された。

certificate_expired
  証明書は、有効期限切れとなったか、あるいは、現在、有効ではない。

certificate_unknown
 

何らかの他の(規定されていない)問題が証明書処理において発生し、それを受容不能と見なす。


illegal_parameter
  そのハンドシェイク中のフィールドは、範囲外であったか、あるいは、他のフィールドと不整合であった。このメッセージは、常に fatal である。


unknown_ca
 

有効な証明書チェーンもしくは部分のチェーンが受け取られたが、その証明書は、その CA 証明書が 配置(locate)できなかった、あるいは、既知の信頼できる(trusted)CA と一致しえなかったので受容されなかった。このメッセージは、常に fatal である。



access_denied
  有効な証明書が受信されたが、アクセス制御が適用されたとき、その送信者は、交渉を進めないことを決断した。このメッセージは、常に fatal である。


decode_error
 

あるメッセージが、decode できなかった。なぜならば、フィールドには規定された範囲外のものがあったから、あるいは、そのメッセージの長さが不正であったからである。このメッセージは、常に fatal であり、決して正しい実装間の通信中で観察されないようにする必要がある。(メッセージがネットワークにおいて壊れたときを除く)


decrypt_error
  署名を正しく検証できないか、あるいは、Finished メッセージを検証できないことを含むハンドシェイクの暗号技術的操作のフィールド。このメッセージは、常に、fatal である。

export_restriction_RESERVED
  このアラートは、TLS の以前のいくつかのバーションにおいて使われた。これは、準拠実装によって送られてはならない(MUST NOT)

protocol_version
 

クライアントが交渉する試みたプロトコルバーションは、認識されたが、サポートされていない。(例えば、古いプロトコルバーションは、セキュリティの理由で避けられる可能性がある。)このメッセージは、常に fatal である。



insufficient_security
 

そのサーバがクライアントによってサポートされている cypher よりもセキュアなものを要求することに起因して、具体的に交渉が失敗したとき、handshake_failure の代わりに返される。このメッセージは、常に fatal である。



internal_error
 

ピア、もしくは、プロトコルの正しさと無関連な内部エラー(例: memory allocation failure)は、継続することを不可能にする。このメッセージは、常に fatal である。



user_canceled
  このハンドシェイクは、プロトコル failure とは関係無い、いくつかの理由(reason)用にキャッシュされる。そのユーザが、ハンドシェイクが完了した後の操作をキャンセルする場合、close_notify を送信することによって、単にそのコネクションを閉じることが、より適切である。このアラートは、close_notify を伴う必要がある。このメッセージは、一般に warning である。

no_renegotiation
 

hello リクエストに応じてクライアントによって送られるか、あるいは、最初の handshaking 後にクライアント hello に応じてサーバによって送られる。これらのいずれも、通常、renegotiation をもたらす。; 不適切なとき、その受信者は、このアラートで応答する必要がある。その時点で、当初の要求者(requester)は、「そのコネクションを続行するか否か?」を判断できる。これが適切となる場合のひとつの事例は、サーバがあるリクエストを満たすためにプロセスを量産した場合である。; その過程は、開始時にセキュリティパラメータ (鍵長、認証等)を受信する可能性があり、以降のこれらのパラメータに対する変更点を通信することは、困難である可能性がある。このメッセージは、常に warning である。


unsupported_extension
 

「それらは、対応するクライアント hello を入れていなかった」という拡張を含む extended サーバ hello を受信するクライアントによって送られる。このメッセージは、常に fatal である。


新しいアラート値が、12 節に記述されているように IANA によって割り当てられた。

7.3. ハンドシェイクプロトコル概要 English

セッション状態の暗号技術的パラメータは、TLS ハンドシェイクプロトコルによって作り出される。これは、TLS レコード層の最上部で動作する。TLS のクライアントおよびサーバが、まず、通信を開始するとき、それらは、プロトコルバーションに合意し、暗号アルゴリズムを選択し、オプションとして相互に認証(authenticate)し、shared secrets を生成するために公開鍵暗号化テクニックを使う。

TLS ハンドシェイクプロトコルは、下記のステップを含む。:

「上位層は、TLS が常に 2 つのピア間で可能性在る最強のコネクションを交渉するか否かに、過度に依存しては、いけないこと 」に注意。中間者攻撃(man-in-the-middle 攻撃)の攻撃者が 2 つの主体をサポートしている最低のセキュア手法にまで落とすことを試みることができる数多くの方法がある。このプロトコルは、このリスクを最小化するように設計されたが、いまだに攻撃法がある。: 例えば、攻撃者は、セキュアサービスが動作しているポート宛のアクセスを妨害(block)する可能性、あるいは、認証されていない(unauthenticated)コネクションを交渉するためにペアを得ることを試みる可能性がある。基礎的なルールは、「高位のレベルは、それらのセキュリティ要件は何であるかを認識可能であり、決して、彼らが要求する情報を、よりセキュアでないチャネル上を転送してはならないこと」である。TLS プロトコルは、あらゆる cipher suite が約束された(promised)レベルのセキュリティを提供するのでセキュアである。: あなたが 3DES と 1024 bit RSA 鍵交換について、証明書を検証したホストと交渉する場合、あなたは、そのセキュリティの程度にあると期待できる。

これらの目標は、ハンドシェイクプロトコルによって達成され、これは、下記のように要約できる。: そのクライアントは、そのサーバが ServerHello メッセージで応答しなければならない相手宛に ClientHello メッセージを送るか、あるいは、fatal エラーが起こり、そのコネクションは、失敗する。ClientHello および ServerHello は、クライアントとサーバ間にセキュリティ拡張機能(capabilities)を確立するために使われる。ClientHello および ServerHello は、下記の属性(attributes)を確立する。: プロトコルバージョン、セッション ID、Cipher Suite および圧縮手法。さらに、ふたつの random な値が生成され、交換される。: ClientHello.random および ServerHello.random。

実際の鍵交換は、4 つまでのメッセージを使う。: ServerCertificate、ServerKeyExchange、ClientCertificate および ClientKeyExchange。
新しい鍵交換手法が、これらのメッセージについてフォーマットを規定すること、および、クライアントとサーバが shared secret について合意することを許容するメッセージの利用を定義することによって作成される可能性がある。この secret は、極めて長くなければならない(MUST)。; 現在、定義されている鍵交換手法は、46 byte 以上の幅がある secret を交換する。

その hello メッセージにしたがって、そのサーバは、それが認証されるべき場合、Certificate メッセージ内で、その証明書を送る。さらに、それが要求される場合(例:そのサーバが証明書をもたない場合、あるいは、その証明書が署名専用の場合)、ServerKeyExchange メッセージが送られる可能性がある。そのサーバが認証される場合、これは、選択された cipher suite に適切である場合、証明書をそのクライアントから要求する可能性がある。次に、そのサーバは、「そのハンドシェイクの hello メッセージフェイズは、完了したこと」を示しながら ServerHelloDone メッセージを送る。そして、そのサーバは、クライアント応答を待つ。そのサーバが CertificateRequest メッセージを送っていた場合、そのクライアントは、その Certificate メッセージを送らなければならない(MUST)。ClientKeyExchange メッセージは、今や送られ、そのメッセージの内容は、ClientHello と ServerHello 間で選択された公開鍵アルゴリズムに依存する。そのクライアントが証明書を署名する能力をもって送信した場合、ディジタル的に署名された CertificateVerify メッセージは、その証明書中のプライベート鍵の保持を明示的に検証するために送られる。

この時点で、ChangeCipherSpec メッセージは、そのクライアントによって送信され、そのクライアントは、pending Cipher Spec を current Cipher Spec にコピーする。そして、そのクライアントは、ただちに、その新しいアルゴリズム、鍵および secrets のもとで Finished メッセージを送る。そのサーバは、応答として、自身の ChangeCipherSpec メッセージを送り、現在の Cipher Spec の保留(pending)を転送し、その新しい Cipher Spec のもとで、その Finished メッセージを送る。この時点で、そのハンドシェイクは完成し、そのクライアントおよびサーバは、アプリケーション層データの交換を開始できる。(下記のフローチャートを参照。)アプリケーションデータは、最初のハンドシェイクの完了前に(TLS_NULL_WITH_NULL_NULL 以外の cipher suite が確立される前に)送られてはならない(MUST NOT)

   クライアント                                      サーバ
   ClientHello                  -------->
                                                   ServerHello
                                                  Certificate*
                                            ServerKeyExchange*
                                           CertificateRequest*
                                <--------      ServerHelloDone
   Certificate*
   ClientKeyExchange
   CertificateVerify*
   [ChangeCipherSpec]
   Finished                     -------->
                                            [ChangeCipherSpec]
                                <--------             Finished
   Application Data             <------->     Application Data
          図 1.  ハンドシェイク全体についてのメッセージフロー

* Indicates optional or situation-dependent メッセージs that are not always sent。

注:pipeline stalls の回避を支援するために、ChangeCipherSpec は、独立した TLS プロトコルコンテンツ種別であり、実際には TLS ハンドシェイクメッセージではない。

そのクライアントおよびサーバが 、以前のセッションを中断すること、あるいは、(新しいセキュリティパラメータを交渉する代わりに)既存セッションを複成することを判断するとき、そのメッセージフローは、下記のようになる。:

そのクライアントは、ClientHello を、回復(resume)されるべきセッションのセッション ID を使って送る。次に、そのサーバは、そのセッションのキャッシュ内に一致するものがないかについてチェックする。一致が発見され、かつ、そのサーバが特定されたセッション状態の下で、そのコネクションを再確立することを望んでいる場合、それは、ServerHello を同一のセッション ID 値と共に送る。この点において、クライアントとサーバの両方は、ChangeCipherSpec メッセージを送り、直接、Finished メッセージに進まなければならない(MUST)。ひとたび、その再確立が完了すると、そのクライアントとサーバは、アプリケーション層データを交換することを開始する可能性がある(MAY)。(下記のフローチャートを参照。)セッション ID が一致が見つからない場合、そのサーバは、新しいセッション ID を生成し、その TLS クライアントおよびサーバは、ハンドシェイク全部を行う。

   クライアント                                      サーバ
   ClientHello                   -------->
                                                    ServerHello
                                             [ChangeCipherSpec]
                                 <--------             Finished
   [ChangeCipherSpec]
   Finished                      -------->
   Application Data              <------->     Application Data
       図 2.  省略されたハンドシェイクについてのメッセージフロー

各メッセージの内容および顕著な点(significance)は、下記の節において詳細に提供される。

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

TLS ハンドシェイクプロトコルは、TLS Record プロトコルの定義された高位レベルクライアントのひとつである。このプロトコルは、セッションの secure attributes を交渉するために使われる。ハンドシェイクメッセージは、TLS レコード層宛に供給される。ここで、それらは、ひとつ、もしくは、複数の TLSPlaintext 構造体内で カプセル化される。これは、現在の active セッション状態によって規定されているように処理され、転送される。

   enum {
       hello_request(0), client_hello(1), server_hello(2),
       certificate(11), server_key_exchange (12),
       certificate_request(13), server_hello_done(14),
       certificate_verify(15), client_key_exchange(16),
       finished(20), (255)
   } HandshakeType;
   struct {
       HandshakeType msg_type;    /* handshake type */
       uint24 length;             /* bytes in メッセージ */
       select (HandshakeType) {
           case hello_request:       HelloRequest;
           case client_hello:        ClientHello;
           case server_hello:        ServerHello;
           case certificate:         Certificate;
           case server_key_exchange: ServerKeyExchange;
           case certificate_request: CertificateRequest;
           case server_hello_done:   ServerHelloDone;
           case certificate_verify:  CertificateVerify;
           case client_key_exchange: ClientKeyExchange;
           case finished:            Finished;
       } body;
   } Handshake;

ハンドシェイクプロトコルメッセージは、それらが送られなければならない(MUST)順に下記に表現されている。; ハンドシェイクメッセージの予期しない順序の送信は、fatal error をもたらす。しかし、必要とされない(unneeded)ハンドシェイクメッセージは、省略できる。順序(ordering)についてのひとつの例外に注意。: Certificate メッセージは、そのハンドシェイクにおいて 2回((まず)サーバからクライアント宛、次にクライアントからサーバ宛)使われ、その最初の場所にのみ記述される。これらの順序のルールによって制約されていないメッセージとは、HelloRequest メッセージである。これは、いつでも送られる可能性があるが、これは、ハンドシェイクの途中で到達する場合、そのクライアントによって無視される必要がある(SHOULD)

12 節に記述したように、新しいハンドシェイク メッセージ種別が、IANA によって割り当てられる。

7.4.1. Hello メッセージ English

hello メッセージは、セキュリティ拡張(enhancement)能力(capabilitiy)をクライアントとサーバの間で交換するために使われる。新しいセッションが始まるとき、そのレコード層のコネクション状態暗号化、ハッシュアルゴリズムおよび圧縮アルゴリズムは、null に初期化される。現在のコネクション状態は、renegotiation メッセージ用に使われる。

7.4.1.1. Hello リクエスト English

いつこのメッセージが送られるか?:

このメッセージの意味:

このメッセージの構造体:

このメッセージは、ハンドシェイクを通じて維持管理されており、Finished メッセージおよび証明書検証メッセージにおいて使われている、管理されているメッセージ hashes 中に含まれてはならない(MUST NOT)

7.4.1.2. クライアント Hello English

いつこのメッセージが送られるか?:

このメッセージの構造体:

ClientHello メッセージは、可変長のセッション識別子を含む。空でない場合、その値は、同一のクライアントと サーバ間のセッションを識別する。そのセキュリティパラメータは、そのクライアントが再利用することを望むものである。そのセッション識別子は、以前のコネクションからのもの、このコネクションからのもの、あるいは、現在、生きている他方のコネクションからのものである可能性がある(MAY)。2 番目のオプションは、そのクライアントが、その random 構造体、および、取得されたコネクションの値を更新することのみを望む場合、有用である。そして、3 番目のオプションは、その full ハンドシェイクプロトコルを繰り返すこと無しに、いくつかの独立したセキュアなコネクションを確立することを可能にする。これらの独立したコネクションは、逐次(sequential)あるいは同時(simultaneous)に発生する可能性がある。; セッションID は、それを交渉するハンドシェイクが Finished メッセージの交換で完了するときに有効になり、経年に起因して、あるいは、fatal エラーがそのセッションと関連するコネクションに発生したことによって削除されるまで固執(persist)する。その SessionID の実際の内容は、そのサーバによって定義される。

      opaque SessionID<0..32>;

警告: SessionID は、暗号化もしくは immediate MAC による防護無しで転送されるので、サーバは、セッション識別子中に confidential 情報を配置したり、あるいは、偽の(fake)セッション識別子の内容が、いかなるセキュリティの侵害ももたらしたりしてはならない(MUST NOT)。(「SessionID を含むハンドシェイク全体としての内容は、そのハンドシェイクの最後において交換された Finished メッセージによって防護されていること」に注意。)

クライアントからサーバ宛に ClientHello メッセージ中で渡される cipher suite リストは、クライアントの選好(好まれる選択肢が最初)の順に、そのクライアントによってサポートされる暗号アルゴリズムの組み合わせを含む。各 cipher suite は、鍵交換アルゴリズム、バルク暗号化アルゴリズム(including secret 鍵長)、MAC アルゴリズムおよび PRF を定義する。そのサーバは、ある cipher suite を選択する。あるいは、受容可能な選択肢が提供されなかった場合、ハンドシェイク失敗アラートを返して、そのコネクションを閉じる。そのリストが、サーバが認識・サポート・利用しようとしない cipher suites を含む場合、そのサーバは、それらの cipher suites を無視し、通常どおり、残りのものを処理しなければならない(MUST)

      uint8 CipherSuite[2];    /* Cryptographic suite selector */

ClientHello は、クライアントの選好に従って並べられた、そのクライアントによってサポートされる圧縮アルゴリズムのリストを含む。

      enum { null(0), (255) } CompressionMethod;
      struct {
          ProtocolVersion client_version;
          Random random;
          SessionID session_id;
          CipherSuite cipher_suites<2..2^16-2>;
          CompressionMethod compression_methods<1..2^8-1>;
          select (extensions_present) {
              case false:
                  struct {};
              case true:
                  Extension extensions<0..2^16-1>;
          };
      } ClientHello;

TLS は、ある拡張ブロック中の compression_methods フィールドに続く拡張を許容する。拡張の存在は、「ClientHello の最後にある compression_methods に追随するバイト列が存在するか否か?」を判定することによって検出できる。「オプションとしてのデータを検知する、この手法は、可変長フィールドをもつ通常の TLS 手法と区別するが、これは、拡張が定義される前に TLS との互換性用に使われること」に注意。

client_version
  by which the クライアント wishes to communicate during このセッション
TLS プロトコルのバージョン。これは、クライアントによってサポートされている最新バージョンである必要がある(SHOULD)。このバーションの仕様について、そのバーションは、3.3 となる。(下位互換性の詳細については、Appendix E 参照。)

random
  クライアント-生成された random 構造体。

session_id
 

クライアントがこのコネクション用に使うことを望むセッションのID。このフィールドは、session_id が利用不能な場合、あるいは、クライアントが新しいセキュリティパラメータを生成することを望む場合、空である。


cipher_suites
  これは、クライアントによってサポートされている暗号技術的なオプションのリストであり、そのクライアントの最初の選好を最初に伴う。session_id フィールドが空でない(implying a セッション resumption リクエスト)場合、この vector は、少なくとも、そのセッションからの cipher_suite を含まなければならない(MUST)。値は、Appendix A.5 に定義されている。

compression_methods
  これは、クライアントによってサポートされている圧縮手法のリストであり、クライアント preference によってソートされる。session_id フィールドが 空でない(セッション回復(resumption)リクエストを意味する)場合、それは、そのセッションから compression_method を含まなければならない(MUST)。この vector は、含まなければならない(MUST)。そして、すべての実装は、 CompressionMethod.null をサポートしなければならない(MUST)。それゆえ、クライアントおよびサーバは、常に、圧縮手法に合意できる。

extensions
  クライアントは、サーバから、拡張 フィールド中のデータを送ることによって拡張された機能を要求する可能性がある(MAY)。実際の "Extension"フォーマットは、7.4.1.4 節中に定義されている。

クライアントが、拡張を使う追加的な機能を要求し、かつ、この機能がそのサーバによってサポートされていない場合、そのクライアントは、そのハンドシェイクを abort する可能性がある(MAY)。サーバは、この拡張 フィールドをもつ ClientHello メッセージと、もたない ClientHello メッセージの両方を受容しなければならない(MUST)。そして、(他のすべてのメッセージと同様に)それは、「そのメッセージ中のデータの量が、これらのフォーマットのひとつと正確に一致すること」をチェックしなければならない(MUST)。;
not
場合、それは、fatal "decode_error" アラートを送らなければならない(MUST)

ClientHello メッセージを送った後、そのクライアントは、ServerHello メッセージを待つ。HelloRequest を除く、そのサーバによって返される、あらゆるハンドシェイクメッセージは、fatal エラーとして扱われる。

7.4.1.3. サーバ Hello English

いつこのメッセージが送られるか?:

このメッセージの構造体:

      struct {
          ProtocolVersion server_version;
          Random random;
          SessionID session_id;
          CipherSuite cipher_suite;
          CompressionMethod compression_method;
          select (extensions_present) {
              case false:
                  struct {};
              case true:
                  Extension extensions<0..2^16-1>;
          };
      } ServerHello;

拡張の存在は、「ServerHello の終端に compression_method フィールドに追随するバイト列が存在するか否か?」を判定することによって検出されうる。

server_version
  このフィールドは、クライアント hello 中のクライアントによって示唆されたものの低い方、および、サーバによってサポートされた最も高いものを含む。このバーションの仕様について、そのバーションは、3.3 である。(下位互換性の詳細については Appendix Eを参照。)

random
  この構造体は、サーバによって生成され、ClientHello.random から独立して生成されなければならない(MUST)

session_id
 

これは、このコネクションに対応する セッションの ID である。ClientHello.session_id が空でなかった場合、そのサーバは、そのセッションキャッシュ内に一致がないかを調べる。一致するものが見つかり、かつ、そのサーバが規定されたセッション状態を使って新しいコネクションを確立することを望む場合、そのサーバは、そのクライアントによってサポートされたものと同一の値で応答する。これは、中断されたセッションを示し、「それらの主体は、Finished メッセージに直接、進めなければならない」と命令する。さもなければ、このフィールドは、新しいセッションを識別する異なる値を含む。そのサーバは、「そのセッションは、キャッシュされず、それゆえ、中断されえないこと 」を示すために空の session_id を返す可能性がある。あるセッションが中断(resume)される場合、これは、当初、交渉されたのと同一の cipher suite を使って、中断されなければならない。「そのサーバは、たとえ、めったに session_id を提供されたことがなかった場合でも、あらゆるセッションを中断するという要件は無いこと」に注意。クライアントは、交渉全体(full negotiation)(新しいcipher suites を交渉することを含む)を、あらゆりハンドシェイクにおいて行うことに備えなければならない(MUST)


cipher_suite
  ClientHello.cipher_suites 中のリストからサーバによって選択された単一の cipher suite。esumed セッションについて、このフィールドは、そのセッションが中断された状態からの値である。

compression_手法
  ClientHello.compression_methods 中のリストからサーバによって選択された単一の圧縮アルゴリズム。中断されたセッションについて、このフィールドは、resumed セッション状態からの値である。

extensions
  拡張のリスト。 「そのクライアントによって提供された拡張のみが、そのサーバのリスト中に存在できること」に注意。


7.4.1.4. Hello 拡張 English

拡張フォーマットは、下記のとおり。:

      struct {
          ExtensionType extension_type;
          opaque extension_data<0..2^16-1>;
      } Extension;
      enum {
          signature_algorithms(13), (65535)
      } ExtensionType;

ここでは:

拡張の初期設定は、副読本 [TLSEXT] 中に定義されている。拡張種別のリストは、12 節に記述されているように、IANA によって維持管理される。

拡張種別は、同一の拡張種別が対応する ClientHello 中に現れない限り ServerHello 中に現れなければならない(MUST NOT)。クライアントが関連する ClientHello において要求しなかった ServerHello 中の拡張種別を受け取る場合、それは、そのハンドシェイクを unsupported_extension fatal アラートで中断(abort)しなければならない(MUST)

それにもかかわらず、"server-oriented" 拡張は、将来、このフレームワーク内で提供される可能性がある。このような拡張(例: type x のもの)は、そのクライアントに、まず、「これは、その拡張種別をサポートすること」を示す空の extension_data を伴う ClientHello 中に type x の拡張を送ることを要求する。この場合、クライアントは、その拡張種別を理解する能力を提供しており、そのサーバは、その提供に基づいてクライアントを得ている。

異なる種別の複数の拡張が ClientHello もしくは ServerHello メッセージ中に存在するとき、その拡張は、あらゆる順序で現れる可能性がある(MAY)。同一の種別のひとつより多くの拡張が存在してはならない(MUST NOT)

最後に、「拡張は、新しいセッションを開始するとき、および、セッション回復(resumption)を要求するときの両方、送信される可能性があること」に注意。まさに、セッション resumption を要求するクライアントは、一般に、「そのサーバは、この リクエストを受領するか否か?」を知らない。それゆえ、それは、回復を試みなかった場合に送られたであろうものと同一の拡張を送る必要がある(SHOULD)

一般に、各拡張種別の規定は、full ハンドシェイクと、セッション再開(resumption)の両方において、その拡張の影響を記述することを必要とする。大部分の現在の TLS 拡張は、セッションが開始されたときにのみ関連する。: より古いセッションが中断されたとき、そのサーバは、クライアント Hello 中のこれらの拡張を処理せず、サーバ Hello 中のものを含まない。しかし、拡張には、セッション再開(resumption)において、異なるふるまいを規定する可能性があるものがある。

新しい機能と既存の機能の間でこのプロトコル中に起きる可能性がある適切(および不適切)な相互作用か存在する。これは、全体のセキュリティの顕著な低下をもたらす可能性がある。下記の考慮事項が、新しい拡張を設計するとき、考慮される必要がある。:

7.4.1.4.1. 署名アルゴリズム English

クライアントは、そのサーバ宛に「どの署名/ハッシュアルゴリズムのペアがディジタル署名において使われる可能性があるか?」示すために "signature_algorithms" 拡張を使う。この拡張の "extension_data" フィールドは、"supported_signature_algorithms" 値を含む。

      enum {
          none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5),
          sha512(6), (255)
      } HashAlgorithm;
      enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }
        SignatureAlgorithm;
      struct {
            HashAlgorithm hash;
            SignatureAlgorithm signature;
      } SignatureAndHashAlgorithm;
      SignatureAndHashAlgorithm
        supported_signature_algorithms<2..2^16-2>;

各 SignatureAndHashAlgorithm 値は、そのクライアントが 検証することを望んでいる単一のハッシュと署名のペアを掲げる。その値は、選好される降順に示される。

注: すべての署名アルゴリズムおよびハッシュアルゴリズムが、ある実装によって受容される可能性があるわけではない(例:DSA with SHA-1, ただし SHA-256ではない)ので、ここにアルゴリズムは、ペアで掲げられる。

 

>
hash
  このフィールドは、使われる可能性があるハッシュアルゴリズムを示す。この値は、順に、unhashed データ、MD5 [MD5]、SHA-1、SHA-224、SHA-256、SHA-384 および SHA-512 [SHS] についてのサポートを示す。"none" という値は、署名する前にハッシュ化することを要求しない署名アルゴリズムの場合、将来の拡張可能性のために提供される。

signature
  このフィールドは、使われる可能性がある署名アルゴリズムを示す。その値は、順に、anonymous 署名、RSASSA-PKCS1-v1_5 [PKCS1]、DSA [DSS] および ECDSA [ECDSA] を示すものを含む。その "anonymous" 値は、この文脈において無意味ではあるが、7.4.3 節 において使われる。これは、この拡張中に現れてはならない(MUST NOT)

この拡張の semantics は、その cipher suite がハッシュアルゴリズムではなく許可可能な(permissible)署名アルゴリズムを示すので、何となく複雑になっている。7.4.2 節7.4.3 節 では、適切なルールを記述している。

クライアントが(この節中に掲げられている)デフォルトのハッシュアルゴリズムおよび署名アルゴリズムのみをサポートする場合、それは、signature_algorithms 拡張を省略する可能性がある(MAY)。そのクライアントが、そのデフォルトアルゴリズムをサポートしない場合、あるいは、他のハッシュと署名のアルゴリズムをサポートする場合、(そして、そのサーバによって送られたメッセージ(すなわち、サーバ証明書およびサーバ鍵交換)を検証するために、それらを使うことを望んでいる場合、)それは、受領することを望んでいるアルゴリズムを掲げている signature_algorithms 拡張を送らなければならない(MUST)

クライアントが signature_algorithms 拡張を送らない場合、サーバは、下記の事項を行わなければならない(MUST)。:

注: これは、明示的なルールが無い TLS 1.1からの変更点であるが、実際問題として、人は、「そのペアは、MD5 および SHA-1 をサポートする」と想定できる。

注: この拡張は、1.2 より前のバージョンの TLS 用には有意でない。クライアントは、それらが以前のバーションを提供している場合、それを提供しなければならない(MUST NOT)。しかし、たとえクライアントがこれを提供する場合でも、[TLSEXT] 中に規定されたルールは、サーバが理解できない拡張を無視することを要する。

サーバは、この拡張を送らなければならない(MUST NOT)。TLS サーバは、この拡張の受信をサポートしなければならない(MUST)

セッション回復(resumption)を行うとき、この拡張は、サーバ Hello 含まれていない。そして、そのサーバは、クライアント Hello(があれば、その)中の、その拡張を無視する。

7.4.2. サーバ証明書 English

いつこのメッセージが送られるか?:

このメッセージの意味:

このメッセージの構造体:

      opaque ASN.1Cert<1..2^24-1>;
      struct {
          ASN.1Cert certificate_list<0..2^24-1>;
      } Certificate;
certificatelist
 

これは、一連(チェーン)の証明書である。送信者の証明書は、リスト中の最初にこなければならない(MUST)。追随する各証明書は、直接、先行するものを認定(certify)しなければならない(MUST)。証明書検証は、「root 鍵が独立して配布されること」を要求するので、 その root CA を規定する自己署名証明書は、「遠隔の終端は、いかなるときにもそれを検証するために、既に保持していなければならない」という想定のもとで、そのチェーンから省略される可能性がある(MAY)


同一のメッセージ種別および構造体が、証明書リクエストメッセージに対するクライアントの response 用に使われる。「クライアントは、サーバの認証(authentication)リクエストに応じて送る適切な証明書をもたない場合、証明書を送らない可能性がある(MAY)こと」に注意。

注: PKCS #7 [PKCS7] は、証明書 vector用のフォーマットとして使われない。なぜならば、PKCS #6 [PKCS6] extended 証明書は、使われていないからである。また、PKCS #7 は、SEQUENCE ではなく SET を定義し、そのリストを構文解析する(parsing)タスクをより困難にする。

下記のルールが、そのサーバによって送られた証明書に適用される。:

そのクライアントが "signature_algorithms" 拡張を提供した場合、そのサーバによって提供された、すべての証明書は、その拡張中に現れるハッシュ/署名アルゴリズムのペアによって署名されなければならない(MUST)。「これは、『ある署名アルゴリズム用の鍵を含む証明書は、異なる署名アルゴリズム(例: DSA 鍵で署名された RSA 鍵)を使って署名されること』を意味する可能性がある(MAY)こと」に注意。これは、TLS 1.1 から始まったことであり、「それらのアルゴリズムが同一であること」を要求する。「これは、DH_DSS, DH_RSA, ECDH_ECDSA および ECDH_RSA 鍵交換アルゴリズムは、その証明書に署名するのに使われるアルゴリズムを制限しないことも意味すること」に注意。Fixed DH 証明書は、その拡張中に現れるあらゆるハッシュ/署名アルゴリズムのペアによって署名される可能性がある(MAY)。DH_DSS, DH_RSA, ECDH_ECDSA および ECDH_RSA という名前は、経緯に由来するもの(historical)である。

そのサーバが複数の証明書をもつ場合、それは、上術のクライテリアに基づくもののひとつ(他のクライテリアに加えて、トランスポート層の終点(endpoint)、ローカル設定および性能、等)を選択する。そのサーバが単一の証明書をもつ場合、それは、「これらのクライテリアに合致すること」を検証することを試みる必要がある(SHOULD)

「現在 TLS と共には使えないアルゴリズム、かつ/または、アルゴリズムの組み合わせを使う証明書が存在すること 」に注意。例えば、RSASSA-PSS 署名鍵 (id-RSASSA-PSS OID in SubjectPublicKeyInfo) をもつ証明書は、TLS が対応する署名アルゴリズムを定義していないので、使えない。

新しい鍵交換手法を規定する cipher suites は、TLS プロトコル用に規定されているので、それらは、証明書フォーマット、および、要求された符号化がされた鍵とする情報を意味する。

7.4.3. サーバ鍵交換メッセージ English

いつこのメッセージが送られるか?:

下記の鍵交換手法のために ServerKeyExchange メッセージを送ることは、不正である。:

RSA
DH_DSS
DH_RSA

このメッセージの意味:

このメッセージの構造体:

      enum { dhe_dss, dhe_rsa, dh_anon, rsa, dh_dss, dh_rsa
            /* 拡張される可能性がある。(例:ECDH について [TLSECC] 参照)*/
           } KeyExchangeAlgorithm;
      struct {
          opaque dh_p<1..2^16-1>;
          opaque dh_g<1..2^16-1>;
          opaque dh_Ys<1..2^16-1>;
      } ServerDHParams;     /* 超短期(Ephemeral)DH パラメータ */
      dh_p
         The prime modulus used for the Diffie-Hellman 処理。
      dh_g
         The generator used for the Diffie-Hellman 処理。
      dh_Ys
         サーバの Diffie-Hellman 公開値 (g^X mod p)。
      struct {
          select (KeyExchangeAlgorithm) {
              case dh_anon:
                  ServerDHParams params;
              case dhe_dss:
              case dhe_rsa:
                  ServerDHParams params;
                  digitally-signed struct {
                      opaque client_random[32];
                      opaque server_random[32];
                      ServerDHParams params;
                  } signed_params;
              case rsa:
              case dh_dss:
              case dh_rsa:
                  struct {} ;
                 /* メッセージは、rsa、dh_dss について省略される。*/
/* そして、dh_rsa は、拡張される可能性がある。(例:ECDH について [TLSECC] 参照) */ }; } ServerKeyExchange;
      params
         そのサーバの鍵交換パラメータ。
      signed_params
         非匿名鍵交換用に、サーバの鍵交換パラメータ上の署名。

そのクライアントが"signature_algorithms" 拡張を提示した場合、その署名アルゴリズムおよびハッシュアルゴリズムは、その拡張中に掲げられたペアでなければならない(MUST)。「ここに不整合の可能性があること 」に注意。例えば、そのクライアントが DHE_DSS 鍵交換を提示しても、あらゆる DSA ペアを、その "signature_algorithms" 拡張から省略する可能性がある。正しく交渉するようにするため、そのサーバは、あらゆる cipher suites 候補を選択する前に、その "signature_algorithms" 拡張に照らしてチェックしなければならない(MUST)。これは、いささか inelegant であるが、当初の cipher suite 設計への変更を最小化するために設計された妥協案である。

さらに、そのハッシュアルゴリズムおよび署名アルゴリズムは、そのサーバのエンド主体(end-entity)証明書中の鍵と互換性がなければならない(MUST)。RSA 鍵は、あらゆる許容されるハッシュアルゴリズムと共に使われ、証明書中に制約(restriction)(がある場合、制約)の対象となる可能性がある(MAY)

DSA 署名は、ハッシュアルゴリズムの、いかなる secure indication も含まないので、複数のハッシュが、あらゆる鍵と共に使われる可能性がある場合、ハッシュ substitution のリスクがある。現在、DSA [DSS] は、SHA-1 と共にのみ使われる可能性がある。将来、改訂される DSS [DSS-3] は、他のダイジェストアルゴリズムを DSA と共に利用することを許容することが期待されると共に、「どのダイジェストアルゴリズムが各鍵長と共に使われる必要があるか?」に関するガイダンスが期待される 。さらに、将来の [PKIX] の改訂は、「どのダイジェストアルゴリズムが DSA と共に使われるべきものであるか?」を示すため、証明書用のメカニズムを規定する可能性がある。

追加的な cipher suites は、新しい鍵交換アルゴリズムを含む TLS 用に定義されるので、そのサーバ鍵交換メッセージは、その鍵交換アルゴリズムと関連づけられた証明書種別が、そのクライアントが premaster secret を交換するために十分な情報を提供しない場合のみ、送られる。

7.4.4. 証明書リクエスト English

いつこのメッセージが送られるか?:

このメッセージの構造体:

      enum {
          rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4),
          rsa_ephemeral_dh_RESERVED(5), dss_ephemeral_dh_RESERVED(6),
          fortezza_dms_RESERVED(20), (255)
      } ClientCertificateType;
      opaque DistinguishedName<1..2^16-1>;
      struct {
          ClientCertificateType certificate_types<1..2^8-1>;
          SignatureAndHashAlgorithm
            supported_signature_algorithms<2^16-1>;
          DistinguishedName certificate_authorities<0..2^16-1>;
      } CertificateRequest;
certificate_types
  クライアントが提供する可能性がある証明書種別のリスト。

   rsa_sign        RSA 鍵を含む証明書
   dss_sign        DSA 鍵を含む証明書
   rsa_fixed_dh    無期の(static)DH 鍵を含む証明書
   dss_fixed_dh    無期の(static)DH 鍵を含む証明書
supported_signature_algorithms
 

選好の降順に掲げられている、そのサーバが喧噪できるハッシュ/署名アルゴリズムペアのリスト。


certificate_authorities
 

許容可能な certificate_authorities の DN [X501] のリストで、DER-encoded format で表現されたもの。これらの DN は、 root CA 用、もしくは subordinate CA 用に渇望される DN を規定する可能性がある。; それゆえ、このメッセージは、渇望される認可(authorization)space と同様に、既知の roots を記述するために使える。その certificate_authorities リストが空である場合、そのクライアントは、逆に、何らかの外部との調整(arrangement) がないかぎり、適切な ClientCertificateType の、あらゆる証明書を送る可能性がある(MAY)



certificate_types および supported_signature_algorithms フィールドの相互作用は、何とも複雑である。certificate_types は、SSLv3 以来、TLS 中に存在していたが、なぜか規定されなかった。その機能の一致は、supported_signature_algorithms によって、取って代えられた。下記のルールが適用される。:

新しい ClientCertificateType 値が 12 章に記述されているように IANA によって割り当てられた。

注: RESERVED として掲げられている値は、使われない可能性がある。それらは、SSLv3において使われていた。

注:クライアント認証を要求することは、匿名(anonymous)サーバにとっては fatal handshake_failure アラートである。

7.4.5. サーバ Hello Done English

いつこのメッセージが送られるか?:

このメッセージの意味:

このメッセージの構造体:

7.4.6. クライアント証明書 English

いつこのメッセージが送られるか?:

このメッセージの意味:

特記:

「サーバ証明書と同様に、TLS と共には現在、使えないアルゴリズム/アルゴリズムの組み合わせを使う証明書があること」に注意。

7.4.7. クライアント鍵交換 メッセージ English

いつこのメッセージが送られるか?:

このメッセージの意味:

このメッセージの構造体:

7.4.7.1. RSA-Encrypted Premaster Secret メッセージ English

このメッセージの意味:

このメッセージの構造体:

注: PreMasterSecret 中のバーション番号は、ClientHello.client_version 中に、そのクライアントによって提供されるバーションであり、そのコネクション用に交渉されたバーションではない。この機能は、rollback 攻撃を防ぐために設計された。残念ながら、古い実装には、代わりに、その交渉された バーションを使うものがあり、それゆえ、バーション番号をチェックすることは、このような誤った(incorrect)クライアント実装と相互運用することに失敗をもたらす可能性がある。

クライアント実装は、常に PreMasterSecret 中の正しいバーション番号を送らなければならない(MUST)。ClientHello.client_version が TLS 1.1 以降である場合、サーバ実装は、下記の注の中に記述したように、そのバーション番号をチェックしなければならない(MUST)。そのバーション番号が TLS 1.0 以前である場合、サーバ実装は、そのバーション番号をチェックする必要がある(SHOULD)が、 そのチェックを不能にする設定オプションをもつ可能性がある(MAY)。「そのチェックが失敗する場合、PreMasterSecret は、下記のように乱雑化される必要がある(SHOULD)」に注意。

注: Bleichenbacher [BLEI] および Klima ら [KPR03] によって発見された攻撃は、「特定のメッセージが(復号されるとき)正しく PKCS#1 フォーマット化されているか否か?」、「妥当な PreMasterSecret 構造体を含むか否か?」あるいは「正しいバーション番号をもっているか否か?」を明かす TLS サーバを攻撃するために使える。

Klima [KPR03] によって記述されたように、これらの脆弱性は、不正に(incorrectly)フォーマットされたメッセージブロック、かつ/または、一致しないバーション番号を、正しくフォーマットされた RSA ブロックと区別できない作法で扱うことによって避けることができる。換言する。:

  1. 46 random byte の string R を生成する

  2. その plaintext M を復元するために、そのメッセージを復号する

  3. PKCS#1 padding が不正、
    あるいはメッセージ M の長さが明示的に 48 byte ではない場合:
       pre_master_secret = ClientHello.client_version || R
    else If ClientHello.client_version <= TLS 1.0 かつバージョン番号チェックが明示的に不能とされている:
       pre_master_secret = M
    else:
       pre_master_secret = ClientHello.client_version || M[2..47]

「そのクライアントが当初の pre_master_secret において誤ったバーションを送った場合、ClientHello.client_version で pre_master_secret を明示的に構築することは、不適な(invalid)master_secret を作り出すこと」に注意。

代替アプローチのひとつは、バーション番号の不一致を PKCS-1 formatting エラーとして扱い、その premaster secret を完全に乱雑化することである。:

  1. 48 random byte の string R を生成する

  2. そのメッセージを plaintext M を復元するために復号する

  3. PKCS#1 padding が不正であるか、あるいは、メッセージ M の長さが明示的に 48 byte ではない場合:
       pre_master_secret = R
    else If ClientHello.client_version <= TLS 1.0 かつバージョン番号チェックが明示的に不能とされている:
       premaster secret = M
    else If M[0..1] != ClientHello.client_version:
       premaster secret = R
    else:
       premaster secret = M

この construction に対する実践的な攻撃は、知られていないが、Klima ら [KPR03] は、いくつかの論理的な攻撃を記述している。それゆえ、記述された最初の construction が、推奨される(RECOMMENDED)

いずれにせよ、TLS サーバは、RSA で暗号化された premaster secret メッセージが失敗するのを処理する場合、あるいは、そのバーション番号が期待したものではない場合、アラートを生成してはならない(MUST NOT)。代わりに、ランダムに生成された premaster secret と共にそのハンドシェイクを続けなければならない(MUST)。トラブルシューティング目的用に失敗の真の原因(real cause)を記録する(log)ことは、有用である可能性がある。; しかし、その情報を(例えば、タイミング、ログファイルもしくは他のチャネルを通じて)攻撃者に洩らすことを避ける注意をはらう必要がある。

[PKCS1] に定義された RSAES-OAEP 暗号化スキームは、Bleichenbacher 攻撃に対して、よりセキュアである。しかし、以前のバーションの TLS との最大限の互換性のために、この仕様は、RSAES-PKCS1-v1_5 スキームを使う。Bleichenbacher 攻撃の流派(variant)の存在は、上記の推奨事項に従っているとしたら、知られていない。

実装上の注意: Public-key-encrypted データは、opaque ベクトル <0..2^16-1> (4.7 節を参照)として表現される。それゆえ、ClientKeyExchange 中の RSA-encrypted PreMasterSecret は、2 length bytes によって先行される。こららの bytes は、RSA の場合、EncryptedPreMasterSecret は、ClientKeyExchange 中の唯一のデータであり、それゆえ、その長さは、明白に(unambiguously)決定される可能性があるので、冗長となる。SSL v3 仕様は、public-key-encrypted データの符号化について、明確でなかった。それゆえ、多くの SSLv3 実装は、その長さの bytes を含まない。(それらは、その RSA-encrypted データを、直接、ClientKeyExchange メッセージ中に符号化する。)

この仕様は、長さのバイトで完成する EncryptedPreMasterSecret の正しい符号化を要する。結果としての PDU は、多くの SSLv3 実装と互換性が無い。SSLv3 からアップグレードする実装者は、正しい encoding を生成し、受領するように、自身の実装を改変しなければならない(MUST)。SSLv3 および TLS の両方と互換性があることを望む実装者は、彼らの実装のふるまいを、そのプロトコルバーションに依拠するようにする必要がある。

実装上の注意: 「TLS 上の remote timing-based 攻撃は、少なくとも、そのクライアントおよびサーバが同一の LAN 上に在るとき、可能であること」が知られている。したがって、static RSA 鍵を使う実装は、[TIMING] に記述されているように、RSA blinding もしくは何らかの他の anti-timing テクニックを使わなければならない(MUST)

7.4.7.2. クライアント Diffie-Hellman 公開値 English

このメッセージの意味:

このメッセージの構造体:

7.4.8. 証明書 Verify English

いつこのメッセージが送られるか?:

このメッセージの構造体:

7.4.9. Finished English

いつこのメッセージが送られるか?:

このメッセージの意味:

このメッセージの構造体:

これは、Finished メッセージが、そのハンドシェイクにおける適切な時点において、ChangeCipherSpec メッセージによって先行されない場合、fatal エラーである。

handshake_messages という値は、ClientHello に始まり、すべてのハンドシェイクメッセージまで含むが、この Finished メッセージは含まない。これは、7.4.8 節 中の handshake_messages とは異なる可能性がある。なぜならば、これは、CertificateVerify メッセージ(が送られた場合、これ)を含むからである。また、 クライアントによって送られた Finished メッセージ用の handshake_messages は、サーバによって送信される Finished メッセージ 用のものとは異なる。なぜならば、2 番目に送られたものは、以前のものを含むからである。

注: ChangeCipherSpec メッセージ、アラートおよび、いかなる他のレコード種別は、ハンドシェイクメッセージではなく、そのハッシュ計算には含まれない。また、HelloRequest メッセージは、ハンドシェイクハッシュから省略される。

 


6 <- index -> 8