連載NIST PKITS証明書パス検証テストスイート(2)OpenSSLのpkits-test.plは何をしてるのか
前回は証明書チェーンの認証パス検証のテストスイート NIST PKITS のテストを実施するOpenSSLのスクリプト pkits-test.pl を動かすところまでやりました。
今日は、pkits-test.pl のPerlスクリプトを眺めながらOpenSSLを使って何をどんな風にテストケースを実行しているのかを見ていきたいとおもいます。
テストケースの定義
テストケースは配列@testlists
で定義されていて要素2つ、3つ、7つのケースがあります。
my @testlists = (
[ "4.1", "Signature Verification" ], # 要素2つ
[ "4.1.1", "Valid Signatures Test1", 0 ], #要素3つ
[ "4.1.2", "Invalid CA Signature Test2", 7 ],
(中略)
[ # 要素7つ
"4.8.1.1",
"All Certificates Same Policy Test1",
"-policy anyPolicy -explicit_policy",
"True", $nist1, $nist1, 0
],
- 要素2つのケースはテストケースの大きな節番号の表示にだけ使っており、これ自体はテストは行いません。PKITSテストケース仕様書PDFの6ページから4章全体には個々のテストケースが記載されていて4.1節は証明書の署名値検証のテストになります。
- 要素3つのケースは証明書ポリシ処理以外の一般的なテストケースの記述になっており、要素は節番号、テストケース名、コマンドの戻り値の期待値で構成されています。0の場合は正常終了、それ以外の場合はエラー終了です。
- 要素7つのケースは証明書ポリシー処理のテストケースで、4.8節〜4.12節のテストケースは2つを除き全て要素7つのテストケースになっています。7つの要素はそれぞれ以下の通りです:
- (1) テストケースの節以下の番号
- (2) テストケース名(テスト対象データファイルを作るのに使われる。後述)
- (3)
openssl cms -verify
コマンドの引数(ポリシ処理初期値のオプション) - (4)
openssl cms -verify
コマンドに-policy_print
オプションを追加するとポリシー処理結果の詳細が表示されますが、ポリシー明示(explicit policy)だったか結果期待値のフラグ(True or False) - (5)
-policy_print
で表示されるAuthority Policies
の期待値となるポリシーOIDのリスト - (6)
-policy_print
で表示されるUser Policies
の期待値となるポリシーOIDのリスト - (7) コマンドの戻り値の期待値。0なら正常終了、それ以外ならエラー終了
@testlists
の要素数はテストケース数の247個に4.1節〜4.16節の節見出し16個を足した数になっています。
一般的なテストケースのOpenSSL実行コマンド
例えば4.8.1項の正常系の証明書のRSA署名値の検証テストでは、pkits-test.pl
スクリプトからは次のコマンドが呼び出されます。
../util/shlib_wrap.sh ../apps/openssl cms -verify -verify_retcode \
-CAfile pkitsta.pem -crl_check_all \
-x509_strict -policy_check -extended_crl -use_deltas \
-out /dev/null 2>&1 -in pkits/smime/SignedValidSignaturesTest1.eml \
-policy anyPolicy
openssl
コマンドはいろんな用途で使うことができますが、openssl cms
はS/MIME署名暗号メールのメッセージのためのコマンドでopenssl cms -verify
でS/MIME署名メールのメッセージの「検証」を行うことができます。
openssl cms -verify
コマンドの基本形は以下になります。
openssl cms -verify -CAfile 信頼するルート証明書 -in SMIME署名メールメッセージファイル
OpenSSLのソースコードを展開したフォルダで4.8.1のテストを単体で動かすには以下のようにします。
$ cd openssl-3.0.8/test
$ openssl cms -verify -CAfile pkits/pkitsta.pem \
-in pkits/smime/SignedValidSignaturesTest1.eml
すると以下のような出力となり検証成功していることがわかります。
Content-Type: text/plain
This is a sample signed message.
CMS Verification successful
コマンドの戻り値
シェルで実行コマンドの戻り値は、コマンド実行直後に$?
に設定されますが、テストケース4.8.1の戻り値の期待値0と一致していることもわかります。
$ openssl cms -verify -CAfile pkits/pkitsta.pem \
-in pkits/smime/SignedValidSignaturesTest1.eml
$ echo $?
0
-verify_retcode
オプションをつけると異常系のテストケースで期待値と一致するか確認できるようになります。CAのRSA署名値が間違っている4.8.2のテストケースでは戻り値は39になりました。
$ openssl cms -verify -CAfile pkits/pkitsta.pem -verify_retcode \
-in pkits/smime/SignedInvalidCASignatureTest2.eml
(エラーメッセージは省略)
CMS Verification failure
$ echo $?
39
pkits-test.pl
のスクリプトの中で異常終了時には32を足すことになっており、4.8.2のテストケースの期待値は7なので
期待値 7 + 32 == 結果リターンコード 39
と期待値と一致します。
テストデータのS/MIME署名メッセージファイル
pkits-test.pl
スクリプトでは、テストケース毎のS/MIME署名メールファイルの有効性の検証をすることにより、期待値と一致するのかを確認するわけですが、4.8.1のテストケースで、テストケース名から署名メールファイル名は、こんな感じに自動的に変換されます。
"Valid Signatures Test1"
↓空白を取る
"ValidSignaturesTest1"
↓前後に決まったのをつける
"smime/Signed" + "ValidSignaturesTest1" + ".eml"
↓完成
"smime/SignedValidSignaturesTest1.eml"
ファイルを見てみるとMIMEマルチパートでCMS SignedDataの署名データが添付されたメールのメッセージファイルになっています。中身を見てみると、、、
$ cat smime/SignedValidSignaturesTest1.eml
To: recipient@testcertificates.gov ←メールヘッダ
From: sender@testcertificates.gov
Subject: Valid Signatures Test1
MIME-Version: 1.0 ← MIMEマルチパート
Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg="sha-256"; boundary="----AADD99E9055BC286DC1CC034FA3CF1CD" ← メール本文
This is an S/MIME signed message
------AADD99E9055BC286DC1CC034FA3CF1CD ← プレーンテキストのメール本文
Content-Type: text/plain
This is a sample signed message.
------AADD99E9055BC286DC1CC034FA3CF1CD ← CMS SignedData形式の署名の添付ファイル
Content-Type: application/pkcs7-signature; name="smime.p7s"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="smime.p7s"
MIINAwYJKoZIhvcNAQcCoIIM9DCCDPACAQExDzANBglghkgBZQMEAgEFADALBgkq
hkiG9w0BBwGgggb9MIIDfDCCAmSgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBFMQsw
CQYDVQQGEwJVUzEfMB0GA1UEChMWVGVzdCBDZXJ0aWZpY2F0ZXMgMjAxMTEVMBMG
(後略)
メッセージの署名値のCMS SignedDataを見てみると、CRLも含まれていることがわかります。pkits-test.pl
の中で、CRLによる失効検証もしますが、*.eml
に含まれるCRLを使って失効検証をするのだとわかります。
openssl cms -verifyコマンドの追加オプション
NIST PKITSの検証のために指定されている残りのオプション引数をまとめておきます。
分類 | オプション | 内容 |
---|---|---|
検証 | -verify_retcode | パス検証に失敗した際、実行コマンドの戻り値としてゼロ以外の値を返す。 |
検証 | -x509_strict | RFC 5280の検証を厳密に行う。例えばCA証明書の基本制約はクリティカルでなければならないなど。 |
ポリシー | -policy_check | 証明書のポリシ処理を行う。 |
ポリシー | -policy ポリシOID | 初期値 user-initial-policy-set の値として引数の値(OID)を追加する。anyPolicyも指定可能。 |
CRL | -crl_check_all | 適切なCRLを使用して証明書チェーン中の全ての証明書の失効検証を行う。 |
CRL | -extended_crl | 拡張されたCRLの機能、例えばindirect CRLやCRL署名鍵と証明書発行鍵を分けるなどに対応する。 |
CRL | -use_deltas | delta CRLをサポートする。 |
ポリシー処理のテストケースのOpenSSL実行コマンド
ポリシー処理のテストケースはもう少し複雑になります。4.8.3.3のテストケースで実行されるコマンドを見てみましょう。
cmd= ../util/shlib_wrap.sh ../apps/openssl cms -verify -verify_retcode \
-CAfile pkits/pkitsta.pem -crl_check_all -x509_strict -policy_check \
-extended_crl -use_deltas -out /dev/null 2>&1 \
-in pkits/smime/SignedDifferentPoliciesTest3.eml
-policy 2.16.840.1.101.3.2.1.48.1 \
-policy 2.16.840.1.101.3.2.1.48.2 \
-explicit_policy -policy_print
他のテストケースは一つのS/MIME署名データに対して検証成功か失敗かをテストするものでしたが、ポリシー処理関連のテストでは、一つの署名データに対して、幾つかのポリシー関連の初期パラメーターを変えた時に期待通りの検証結果になるかどうかをテストするものになります。
ポリシー処理関係の入力初期値と状態出力の関係
NISTのテストケースやRFC 5280 6章パス検証にあるポリシー関連の入力値と、結果として得られる状態の関係を表したのが下図です。
ポリシー処理関係の入力パラメーター
初期値変数 | 説明 |
---|---|
user-initial-policy-set | 検証者が受け入れ可能な証明書ポリシーOIDの集合。何でも受け入れる場合にはanyPolicyを指定することができる。 |
initial-explicit-policy | user-initial-policy-setの中の少なくとも1つのポリシーが有効でなければならないことを示すフラグ |
initial-policy-mapping-inhibit | ポリシーマッピングが禁止されているかを示すフラグ |
initial-any-policy-inhibit | 証明書チェーン中の証明書の証明書ポリシーにanyPolicyがあることを禁止するかどうかのフラグ |
ポリシー処理関係の入力パラメーターのOpenSSLでの指定方法
ポリシー処理関係の入力パラメーターをopenssl cms -verify
コマンドの追加オプションとしてどのように指定するのかをまとめました。
初期値変数 | opensslでの指定方法 |
---|---|
user-initial-policy-set |
-policy オプションで指定できる。複数のポリシーOIDを指定する場合には-policy 1.2.3.4 -policy 1.2.3.5 のように行う。anyPolicy(oid=2.5.29.32.0)を指定する場合には文字列で-policy anyPolicy のように指定できる。 |
initial-explicit-policy | フラグをTRUEにしたい場合には-explicit_policy オプションをつける。FALSEならつけない。 |
initial-policy-mapping-inhibit | フラグをTRUEにしたい場合には-inhibit_map オプションをつける。FALSEならつけない。 |
initial-any-policy-inhibit | フラグをTRUEにしたい場合には-inhibit_any オプションをつける。FALSEならつけない。 |
ポリシー処理関係のオプションをつけてopenssl cms -verifyする
4.8.1.2のテストケースで、ポリシー明示フラグ(initial-explicit-policy)をつけて、初期ポリシ(user-initial-policy-set)を2.16.840.1.101.3.2.1.48.1
のみ設定して検証してみます。その際、ポリシー処理関連の結果が表示されるように-policy_print
オプションをつけておきます。
$ openssl cms -verify -verify_retcode -CAfile pkits/pkitsta.pem \
-crl_check_all -x509_strict -policy_check -extended_crl -use_deltas \
-out /dev/null 2>&1 -in pkits/smime/SignedAllCertificatesSamePolicyTest1.eml \
-policy 2.16.840.1.101.3.2.1.48.1 -explicit_policy -policy_print
Require explicit Policy: True
Authority Policies:
Policy: 2.16.840.1.101.3.2.1.48.1
Non Critical
No Qualifiers
User Policies:
Policy: 2.16.840.1.101.3.2.1.48.1
Non Critical
No Qualifiers
CMS Verification successful
有効なポリシー2.16.840.1.101.3.2.1.48.1
が見つかって検証成功しているとわかります。
4.8.1.3のテストケースでは、初期ポリシーを*.48.2
に変更すると、通るポリシーがなくて検証失敗します。
$ openssl cms -verify -verify_retcode -CAfile pkits/pkitsta.pem \
-crl_check_all -x509_strict -policy_check -extended_crl -use_deltas \
-out /dev/null 2>&1 -in pkits/smime/SignedAllCertificatesSamePolicyTest1.eml \
-policy 2.16.840.1.101.3.2.1.48.2 -explicit_policy -policy_print
Require explicit Policy: True
Authority Policies:
Policy: 2.16.840.1.101.3.2.1.48.1
Non Critical
No Qualifiers
User Policies: <empty>
CMS Verification failure
ポリシー処理関係の出力パラメーター
出力パラメーター | 説明 |
---|---|
authorities-constrained-policy-set | user-inital-policy-setを使わずに証明書チェーンだけでポリシー処理をした結果の有効な証明書ポリシーOIDの結果の集合。RFC 5280 6章ではこの変数の記載がなく、NIST PKITSのテストケース仕様書でのみ記載されている。 |
user-constrained-policy-set | authorities-constrained-policy-setとuser-initial-policy-setの積集合であり、初期値も反映した受け入れ可能な証明書ポリシーOIDの結果の集合。RFC 5280 6章ではこの変数の記載がなく、NIST PKITSのテストケース仕様書でのみ記載されている。 |
explicit-policy-indicator | 結果として明示的な証明書ポリシーを必要とするかを示すフラグ。RFC 5280 6章ではこの変数の記載がなく、NIST PKITSのテストケース仕様書でのみ記載されている。 |
ポリシー処理関係の出力結果パラメーターとOpenSSLでの表示
openssl cms -verify
コマンドで-policy_print
オプションをつけるとポリシー処理結果に関する情報が表示されます。出力パラメーターと-policy_print
をつけた結果との関係を表にまとめます。
出力パラメーター | 説明 |
---|---|
authorities-constrained-policy-set |
Authority Policies: の下に有効なポリシーの一覧が表示されます。 |
user-constrained-policy-set |
User Policies: の下に有効なポリシーの一覧が表示されます。ここに<empty> でなくポリシーOIDが表示されていれば、ポリシー処理の結果は有効になります。 |
explicit-policy-indicator |
Require explicit Policy: の行にTrue かFalse が表示されます。 |
おわりに
今日は、pkits-test.pl
でNIST PKITSのパス検証をする際に、実際にどんなopensslコマンドを実行しているのかを見てきました。ポイントはこんなとこ。
- パス検証といいながらS/MIME署名メッセージを使ってパス検証のテストをしている。
-
openssl cms -verify
を使って検証している。 - パス検証に必要な証明書とCRLは署名メールのCMS SignedDataに含まれている。
- いろんな検証オプションがフルフルでついている。
- 一般的なケースに対し、ポリシー処理検証のケースでは検証オプションが増える。
長々とすみませんでした。今日はこんなところで。
過去の連載
Discussion