[21] [[TLS Handshake Protocol]] の [DFN[[CODE[[[Certificate]]]]]]
[[メッセージ]]は[[証明書]]を表します。[[サーバー]]から[[クライアント]]へは[[サーバー証明書]]、
[[サーバー]]から[[クライアント]]へは[[クライアント証明書]]となります。

* 仕様書

[REFS[
- [1] '''[CITE@en[RFC 5246 - The Transport Layer Security (TLS) Protocol Version 1.2]] ([TIME[2015-03-25 03:49:56 +09:00]] 版) <https://tools.ietf.org/html/rfc5246#section-7.4.2>'''
- [18] '''[CITE@en[RFC 5246 - The Transport Layer Security (TLS) Protocol Version 1.2]] ([TIME[2015-03-25 03:49:56 +09:00]] 版) <https://tools.ietf.org/html/rfc5246#section-7.4.6>'''
- [16] [CITE[RFC Errata Report]] ([TIME[2015-04-18 16:11:16 +09:00]] 版) <http://www.rfc-editor.org/errata_search.php?rfc=5246>
]REFS]

* 意味

[4] [[サーバー]]からの [CODE[[[Certificate]]]] [[メッセージ]]は、
[[クライアント]]に対して[[サーバー]]の[[証明書鎖]]を伝えるものです [SRC[>>1]]。

[26] [[クライアント]]からの [CODE[[[Certificate]]]] [[メッセージ]]は、
[[サーバー]]に対して[[クライアント]]の[[証明書鎖]]を伝えるものです [SRC[>>18]]。

* 構文

[45] 
[CODE[HandshakeType]] [DFN[[N[11]]]] ([DFN[[CODE[certificate]]]])

-*-*-

[6] [CODE[[[Certificate]]]] [[メッセージ]]は、
0[[バイト]][[以上]]2[SUP[24]]-1[[バイト]][[以下]]の[[証明書]]の[[列]] 
([RUBYB[[[鎖]]]@en[chain]], [[証明書鎖]]) です [SRC[>>1]]。

[17] 各[[証明書]]は、1[[バイト]][[以上]]2[SUP[24]]-1[[バイト]][[以下]]の[[列]]です [SRC[>>1, >>16]]。
どのような[[証明書]]であるべきかにも規定があります (>>11)。

[7] [[送信者]]の[[証明書]]が最初に来なければ[['''なりません''']] [SRC[>>1]]。

;; [39] すなわち[[EE証明書]]が先頭に来ます。

[38] 
その後の[[証明書]]は前の[[証明書]]を直接[[証明]]するものでなければ[['''なりません''']] [SRC[>>1]]。

;; [40] 
つまり[[中間証明書]]が[[小エンディアン]]で並べられます。

;; [36] 
ただし、[[クロスルート証明書]]と呼ばれる技法が使われることがあります。

[8] 
[[ルートCA]]を表す[[自己署名証明書]]は、[[鎖]]から省略して構いません [SRC[>>1]]。
省略しない場合は末尾に来ます。

;; [9] [[検証]]のためには[[ルート証明書]]は[[受信者]]が予め持っておく必要があるからです。

;; [37] [[ルート証明書]]を''省略できる''ということは、含まれていてもいいということです。
実際、含めるサーバーも含めないサーバーも見受けられます。

[41] 
長さ0でもいいということは、[[証明書鎖]]が空になることが (少なくても仕様上は)
あり得るということです。
その場合は当然[[証明書]]による[[検証]]ができず、[[安全]]ではありません。

@@ [46] 
個数0のリスト vs 0バイト列

[44] 
実用上は[[サーバー]]が[[証明書鎖]]を空にすることはまずありません。
[[クライアント]]は[[認証]]が必要な場合以外、空にできます (>>20)。

[42] 
[[証明機関]]の発行する[[証明書]]を利用できないときは、
いわゆる[[オレオレ証明書]]が使われます。
すなわち、その場限りの[[ルート証明書]]に相当する[[EE証明書]]を1つだけ含んだ[[証明書鎖]]になります。

[43] 
[[証明書鎖]]にはバイト長の制限はあるものの、[[証明書]]は何個でも含められます。
[[実際上は十分大きな数で制限][プラットフォーム制限条項]]されます。


-*-*-

[47] 
厳密な話は置いておくとして、 [CODE[Certificate]] の中身をちょっと覗きたいだけの場合、

- [48] 最初の3バイトが列全体のバイト数を表しています。
- [49] 次の3バイトは1個目の証明書のバイト数を表しています。
- [50] そのバイト数分を読み飛ばして、その次の3バイトが2個目の証明書のバイト数を表しています。


* 文脈

[2] [[サーバー]]は、合意した[[鍵交換方式]]が[[認証]]に[[証明書]]を使う場合には、
[CODE[[[Certificate]]]] [[メッセージ]]を送信しなければ[['''なりません''']] [SRC[>>1]]。

[3] [[サーバー]]は、 [CODE[[[ServerHello]]]]
[[メッセージ]]の直後に [CODE[[[Certificate]]]] [[メッセージ]]を送信します [SRC[>>1]]。

[19] [[クライアント]]は、 [CODE[[[ServerHelloDone]]]] [[メッセージ]]を受信した直後に、
([[サーバー]]が [CODE[[[CertificateRequest]]]] [[メッセージ]]で要求していれば)
[CODE[[[Certificate]]]] [[メッセージ]]を送信できます。 [SRC[>>18]]

[20] [[クライアント]]は、適切な[[証明書]]が存在しない時は、
[[証明書]]を含まない ([CODE[[[certificate_list]]]] が長さ0の)
[CODE[[[Certificate]]]] [[メッセージ]]を送信しなければ[['''なりません''']]
[SRC[>>18]]。

[10] [[クライアント]]は、送るべき[[証明書]]がなければ [CODE[[[Certificate]]]]
[[メッセージ]]を送らなくて構いません [SRC[>>1]]。

* 処理

[25] [[クライアント]]は、 [[service identity]] その他[[アプリケーション]]依存の[[証明書]]の検証を行います。

[22] [[サーバー]]は、[[クライアント]]が[[証明書]]を送らなかった場合には、
[[クライアント認証]]なしで[[handshake]]を継続しても構いませんし、
[CODE[[[handshake_failure]]]] [[fatal alert]] で応答しても構いません。 [SRC[>>18]]

[23] [[サーバー]]は、[[クライアント]]の[[証明書鎖]]の一部が受け入れられない
(例えば既知の信頼した [[CA]] が署名していない) 場合、
[[クライアント認証]]なしとみなして[[handshake]]を継続しても構いませんし、
[[fatal alert]] で応答しても構いません。 [SRC[>>18]]

[27] [[サーバー]]は、 [CODE[[[CertificateVerify]]]] [[メッセージ]]の[[検証]]の際や、
[[premaster secret]] の計算に、[[クライアント]]の [CODE[[[Certificate]]]]
を使います [SRC[>>18]]。

* 証明書の選択

[5] [[証明書]]は、両者間で折衝した [[cipher suite]] の[[鍵交換アルゴリズム]]や
[[TLS拡張]]において適当なものでなければ[['''なりません''']] [SRC[>>1, >>18]]。

[11] [[証明書]]は [[PGP]] などで予め明示的に折衝した場合を除き、 
[[X.509]] の v3 [[証明書]]でなければ[['''なりません''']] [SRC[>>1, >>18]]。

[12] [[サーバー]]からの [CODE[[[Certificate]]]] [[メッセージ]]における[[末端実体証明書]]の[[公開鍵]] (と関係する制約) は、
選択した[[鍵交換アルゴリズム]]と互換性があるものでなければ[['''なりません''']] [SRC[>>1]]。

[28] [[クライアント]]からの [CODE[[[Certificate]]]] [[メッセージ]]における[[末端実体証明書]]の[[公開鍵]] (と関係する制約)
は、 [CODE[[[CertificateRequest]]]] [[メッセージ]]で指定された[[証明書]]型と互換性があるものでなければ[['''なりません''']] [SRC[>>18]]。

[29] [[クライアント]]からの [CODE[[[Certificate]]]] [[メッセージ]]における[[証明書]]は、
[CODE[[[CertificateRequest]]]] [[メッセージ]]で空でない [CODE[[[certificate_authorities]]]]
が指定されていた場合、指定されたいずれかの [[CA]] が[[発行]]した[[証明書]]が[[証明書鎖]]のいずれかとして含まれている[['''べきです''']] [SRC[>>18]]。

[13] [[サーバー]]からの [CODE[[[Certificate]]]] [[メッセージ]]における適切な[[証明書]]の選択には、 [[SNI]] や [CODE[[[trusted_ca_keys]]]] の指定があればそれを使います [SRC[>>1]]。

;; 各項も参照。

[14] [[サーバー]]からの [CODE[[[Certificate]]]] [[メッセージ]]においては、
[CODE[[[signature_algorithms]]]] の指定があれば、その[[署名アルゴリズム]]を使った[[証明書]]でなければ[['''なりません''']] [SRC[>>1]]。

[30] [[クライアント]]からの [CODE[[[Certificate]]]] [[メッセージ]]においては、
[[ハッシュアルゴリズム]]と[[署名アルゴリズム]]の組は [CODE[[[CertificateRequest]]]]
[[メッセージ]]での指定に従った[[証明書]]を使わなければ[['''なりません''']] [SRC[>>18]]。

[15] [[サーバー]]は複数の[[証明書]]候補がある時にこうした基準の他、設定や[[ポート番号]]など諸々の基準でいずれかを選択できます。
1つ[[証明書]]がある時もそれらの基準に合致するか検査する[['''べきです''']]。 [SRC[>>1]]

-*-*-

[51] 
多くの実装は [[OpenSSL]] を使っており、 [[OpenSSL]] の [[PEMファイル]]形式で[[証明書鎖]]を指定すると、
[[OpenSSL]] [[サーバー]]がそれを [CODE[Certificate]] 形式に変換して送信することになります。
[SEE[ [[証明書鎖]] ]]

* 中間証明書欠如

[SEE[ [[AIA]] ]]

[31] 
<https://i.allnightnippon.com/>

このサーバー、
[[中間証明書]]を返さなくて[[末端実体証明書]]だけ返してくる。
なのに
[[Windows]]
の
[[Chrome]]
でも
[[IE]]
でもアクセスできてしまう。
[[Linux]]
の
[[wget]],
[[curl]],
[[LibreSSL]]
ではエラーになる。
[[W3C Markup Validator]]
ではエラーになる。
[[Internet Archive]]
ではエラーにならない。
[TIME[2020-08-30T11:00:52.900Z]]

[34] >>31 未だに治っていないがサービスはなくなって他のホストに[[リダイレクト]]される。
たぶんサーバーが消えるか[[証明書]]の期限に達するまでもうこのままだろう。
[TIME[2022-05-25T06:34:08.900Z]]

[32] [CITE@ja[BS11オンデマンド|TOPページ]], [TIME[2022-05-17T03:08:27.000Z]], [TIME[2022-05-17T03:15:22.099Z]] <https://vod.bs11.jp/video/>

[33] >>32 [TIME[2022-05-10]]からの新しい[[末端実体証明書]]が使われてますが、
それに変わった頃から[[中間証明書]]が送信されてこなくなりました。
[[Windows]] の [[Chrome]] では普通にアクセスできてしまいます。
変わってから数日間、修正される様子もないですし、 [[SNS]]
に苦情も出ていないので、多くの環境で正常にアクセスできてしまっているのではないでしょうか。
[TIME[2022-05-17T03:17:14.100Z]]

[35] >>33 その後変わらず。治す気はなさそうだ。 [TIME[2022-05-25T06:35:19.900Z]]

* メモ