OpenSSL コマンドでクロスルート環境の証明書を検証する

久々にクロスルート証明書を触ったら忘れていたのでメモ。
一行で言うと verify する時は -trusted_first を忘れずつける、というだけ。

Symantec のサイトを利用してテストする。

4階層 (クロスルート) は `Class 3 Public Primary Certification Authority` がルートになる。
あらかじめルート証明書を入手しておく。

```console:クロスルート込み4階層の検証
$ echo | openssl s_client -connect www.jp.websecurity.symantec.com:443 -CAfile RootCA_1.cer -verify 3 | tail -n 5
verify depth is 3
depth=3 C = US, O = "VeriSign, Inc.", OU = Class 3 Public Primary Certification Authority
verify return:1
depth=2 C = US, O = "VeriSign, Inc.", OU = VeriSign Trust Network, OU = "(c) 2006 VeriSign, Inc. - For authorized use only", CN = VeriSign Class 3 Public Primary Certification Authority - G5
verify return:1
depth=1 C = US, O = Symantec Corporation, OU = Symantec Trust Network, CN = Symantec Class 3 EV SSL CA - G3
verify return:1
depth=0 1.3.6.1.4.1.311.60.2.1.3 = US, 1.3.6.1.4.1.311.60.2.1.2 = Delaware, businessCategory = Private Organization, serialNumber = 2158113, C = US, postalCode = 94043, ST = California, L = Mountain View, street = 350 Ellis Street, O = Symantec Corporation, OU = Symantec Japan, CN = www.jp.websecurity.symantec.com
verify return:1
DONE

    Start Time: 1417587254
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---
```

3階層は `VeriSign Class 3 Public Primary Certification Authority - G5` がルートになる。
あらかじめルート証明書を入手しておく。

サーバがクロスルート証明書を送るように設定されている場合、
単に verify オプションだけを指定するとエラーになるようだ。

```console:通常の3階層の検証(NG)
$ echo | openssl s_client -connect www.jp.websecurity.symantec.com:443 -CAfile RootCA_2.cer -verify 3 | tail -n 5
verify depth is 3
depth=2 C = US, O = "VeriSign, Inc.", OU = VeriSign Trust Network, OU = "(c) 2006 VeriSign, Inc. - For authorized use only", CN = VeriSign Class 3 Public Primary Certification Authority - G5
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=2 C = US, O = "VeriSign, Inc.", OU = VeriSign Trust Network, OU = "(c) 2006 VeriSign, Inc. - For authorized use only", CN = VeriSign Class 3 Public Primary Certification Authority - G5
verify error:num=27:certificate not trusted
verify return:1
depth=1 C = US, O = Symantec Corporation, OU = Symantec Trust Network, CN = Symantec Class 3 EV SSL CA - G3
verify return:1
depth=0 1.3.6.1.4.1.311.60.2.1.3 = US, 1.3.6.1.4.1.311.60.2.1.2 = Delaware, businessCategory = Private Organization, serialNumber = 2158113, C = US, postalCode = 94043, ST = California, L = Mountain View, street = 350 Ellis Street, O = Symantec Corporation, OU = Symantec Japan, CN = www.jp.websecurity.symantec.com
verify return:1
DONE

    Start Time: 1417587409
    Timeout   : 300 (sec)
    Verify return code: 27 (certificate not trusted)
---
```

サーバが送ってくる証明書を優先してチェーンを作ろうとすることが原因？

```none:verify(1)から抜粋
-trusted_first
    Use certificates in CA file or CA directory before the certificates in the
    untrusted file when building the trust chain to verify certificates.  This is
    mainly useful in environments with Bridge CA or Cross-Certified CAs.
```

-trusted_first オプションをつけるとうまくいく。

```console:通常の3階層の検証(OK)
$ echo | openssl s_client -connect www.jp.websecurity.symantec.com:443 -CAfile RootCA_2.cer -verify 3 -trusted_first | tail -n 5
verify depth is 3
depth=2 C = US, O = "VeriSign, Inc.", OU = VeriSign Trust Network, OU = "(c) 2006 VeriSign, Inc. - For authorized use only", CN = VeriSign Class 3 Public Primary Certification Authority - G5
verify return:1
depth=1 C = US, O = Symantec Corporation, OU = Symantec Trust Network, CN = Symantec Class 3 EV SSL CA - G3
verify return:1
depth=0 1.3.6.1.4.1.311.60.2.1.3 = US, 1.3.6.1.4.1.311.60.2.1.2 = Delaware, businessCategory = Private Organization, serialNumber = 2158113, C = US, postalCode = 94043, ST = California, L = Mountain View, street = 350 Ellis Street, O = Symantec Corporation, OU = Symantec Japan, CN = www.jp.websecurity.symantec.com
verify return:1
DONE

    Start Time: 1417587436
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---
```


## 参考

* https://www.jp.websecurity.symantec.com/developer/step01.html