OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/cert/internal/verify_certificate_chain.h" | 5 #include "net/cert/internal/verify_certificate_chain.h" |
6 | 6 |
7 #include "base/base_paths.h" | 7 #include "base/base_paths.h" |
8 #include "base/files/file_util.h" | 8 #include "base/files/file_util.h" |
9 #include "base/path_service.h" | 9 #include "base/path_service.h" |
10 #include "base/strings/string_split.h" | 10 #include "base/strings/string_split.h" |
(...skipping 21 matching lines...) Expand all Loading... |
32 // Read the full contents of the file. | 32 // Read the full contents of the file. |
33 std::string file_data; | 33 std::string file_data; |
34 if (!base::ReadFileToString(filepath, &file_data)) { | 34 if (!base::ReadFileToString(filepath, &file_data)) { |
35 ADD_FAILURE() << "Couldn't read file: " << filepath.value(); | 35 ADD_FAILURE() << "Couldn't read file: " << filepath.value(); |
36 return std::string(); | 36 return std::string(); |
37 } | 37 } |
38 | 38 |
39 return file_data; | 39 return file_data; |
40 } | 40 } |
41 | 41 |
42 // Adds the certificate |cert_der| as a trust anchor to |trust_store|. | |
43 void AddCertificateToTrustStore(const std::string& cert_der, | |
44 TrustStore* trust_store) { | |
45 ParsedCertificate cert; | |
46 ASSERT_TRUE(ParseCertificate(der::Input(&cert_der), &cert)); | |
47 | |
48 ParsedTbsCertificate tbs; | |
49 ASSERT_TRUE(ParseTbsCertificate(cert.tbs_certificate_tlv, &tbs)); | |
50 TrustAnchor anchor = {tbs.spki_tlv.AsString(), tbs.subject_tlv.AsString()}; | |
51 trust_store->anchors.push_back(anchor); | |
52 } | |
53 | |
54 // Reads a test case from |file_name|. Test cases are comprised of a | 42 // Reads a test case from |file_name|. Test cases are comprised of a |
55 // certificate chain, trust store, a timestamp to validate at, and the | 43 // certificate chain, trust store, a timestamp to validate at, and the |
56 // expected result of verification. | 44 // expected result of verification. |
57 void ReadTestFromFile(const std::string& file_name, | 45 void ReadTestFromFile(const std::string& file_name, |
58 std::vector<std::string>* chain, | 46 std::vector<std::string>* chain, |
59 TrustStore* trust_store, | 47 TrustStore* trust_store, |
60 der::GeneralizedTime* time, | 48 der::GeneralizedTime* time, |
61 bool* verify_result) { | 49 bool* verify_result) { |
62 chain->clear(); | 50 chain->clear(); |
63 *trust_store = TrustStore(); | 51 trust_store->Clear(); |
64 | 52 |
65 std::string file_data = ReadTestFileToString(file_name); | 53 std::string file_data = ReadTestFileToString(file_name); |
66 | 54 |
67 std::vector<std::string> pem_headers; | 55 std::vector<std::string> pem_headers; |
68 | 56 |
69 const char kCertificateHeader[] = "CERTIFICATE"; | 57 const char kCertificateHeader[] = "CERTIFICATE"; |
70 const char kTrustedCertificateHeader[] = "TRUSTED_CERTIFICATE"; | 58 const char kTrustedCertificateHeader[] = "TRUSTED_CERTIFICATE"; |
71 const char kTimeHeader[] = "TIME"; | 59 const char kTimeHeader[] = "TIME"; |
72 const char kResultHeader[] = "VERIFY_RESULT"; | 60 const char kResultHeader[] = "VERIFY_RESULT"; |
73 | 61 |
74 pem_headers.push_back(kCertificateHeader); | 62 pem_headers.push_back(kCertificateHeader); |
75 pem_headers.push_back(kTrustedCertificateHeader); | 63 pem_headers.push_back(kTrustedCertificateHeader); |
76 pem_headers.push_back(kTimeHeader); | 64 pem_headers.push_back(kTimeHeader); |
77 pem_headers.push_back(kResultHeader); | 65 pem_headers.push_back(kResultHeader); |
78 | 66 |
79 bool has_time = false; | 67 bool has_time = false; |
80 bool has_result = false; | 68 bool has_result = false; |
81 | 69 |
82 PEMTokenizer pem_tokenizer(file_data, pem_headers); | 70 PEMTokenizer pem_tokenizer(file_data, pem_headers); |
83 while (pem_tokenizer.GetNext()) { | 71 while (pem_tokenizer.GetNext()) { |
84 const std::string& block_type = pem_tokenizer.block_type(); | 72 const std::string& block_type = pem_tokenizer.block_type(); |
85 const std::string& block_data = pem_tokenizer.data(); | 73 const std::string& block_data = pem_tokenizer.data(); |
86 | 74 |
87 if (block_type == kCertificateHeader) { | 75 if (block_type == kCertificateHeader) { |
88 chain->push_back(block_data); | 76 chain->push_back(block_data); |
89 } else if (block_type == kTrustedCertificateHeader) { | 77 } else if (block_type == kTrustedCertificateHeader) { |
90 AddCertificateToTrustStore(block_data, trust_store); | 78 ASSERT_TRUE(trust_store->AddTrustedCertificate(block_data)); |
91 } else if (block_type == kTimeHeader) { | 79 } else if (block_type == kTimeHeader) { |
92 ASSERT_FALSE(has_time) << "Duplicate " << kTimeHeader; | 80 ASSERT_FALSE(has_time) << "Duplicate " << kTimeHeader; |
93 has_time = true; | 81 has_time = true; |
94 ASSERT_TRUE(der::ParseUTCTime(der::Input(&block_data), time)); | 82 ASSERT_TRUE(der::ParseUTCTime(der::Input(&block_data), time)); |
95 } else if (block_type == kResultHeader) { | 83 } else if (block_type == kResultHeader) { |
96 ASSERT_FALSE(has_result) << "Duplicate " << kResultHeader; | 84 ASSERT_FALSE(has_result) << "Duplicate " << kResultHeader; |
97 ASSERT_TRUE(block_data == "SUCCESS" || block_data == "FAIL") | 85 ASSERT_TRUE(block_data == "SUCCESS" || block_data == "FAIL") |
98 << "Unrecognized result: " << block_data; | 86 << "Unrecognized result: " << block_data; |
99 has_result = true; | 87 has_result = true; |
100 *verify_result = block_data == "SUCCESS"; | 88 *verify_result = block_data == "SUCCESS"; |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 } | 178 } |
191 | 179 |
192 TEST(VerifyCertificateChainTest, ExpiredTarget) { | 180 TEST(VerifyCertificateChainTest, ExpiredTarget) { |
193 RunTest("expired-target.pem"); | 181 RunTest("expired-target.pem"); |
194 } | 182 } |
195 | 183 |
196 TEST(VerifyCertificateChainTest, ExpiredTargetNotBefore) { | 184 TEST(VerifyCertificateChainTest, ExpiredTargetNotBefore) { |
197 RunTest("expired-target-notBefore.pem"); | 185 RunTest("expired-target-notBefore.pem"); |
198 } | 186 } |
199 | 187 |
| 188 TEST(VerifyCertificateChainTest, ExpiredRoot) { |
| 189 RunTest("expired-root.pem"); |
| 190 } |
| 191 |
200 TEST(VerifyCertificateChainTest, TargetNotEndEntity) { | 192 TEST(VerifyCertificateChainTest, TargetNotEndEntity) { |
201 RunTest("target-not-end-entity.pem"); | 193 RunTest("target-not-end-entity.pem"); |
202 } | 194 } |
203 | 195 |
204 TEST(VerifyCertificateChainTest, TargetHasKeyCertSignButNotCa) { | 196 TEST(VerifyCertificateChainTest, TargetHasKeyCertSignButNotCa) { |
205 RunTest("target-has-keycertsign-but-not-ca.pem"); | 197 RunTest("target-has-keycertsign-but-not-ca.pem"); |
206 } | 198 } |
207 | 199 |
208 TEST(VerifyCertificateChainTest, TargetHasPathlenButNotCa) { | 200 TEST(VerifyCertificateChainTest, TargetHasPathlenButNotCa) { |
209 RunTest("target-has-pathlen-but-not-ca.pem"); | 201 RunTest("target-has-pathlen-but-not-ca.pem"); |
210 } | 202 } |
211 | 203 |
212 TEST(VerifyCertificateChainTest, TargetUnknownCriticalExtension) { | 204 TEST(VerifyCertificateChainTest, TargetUnknownCriticalExtension) { |
213 RunTest("target-unknown-critical-extension.pem"); | 205 RunTest("target-unknown-critical-extension.pem"); |
214 } | 206 } |
215 | 207 |
216 TEST(VerifyCertificateChainTest, IssuerAndSubjectNotByteForByteEqual) { | 208 TEST(VerifyCertificateChainTest, IssuerAndSubjectNotByteForByteEqual) { |
217 RunTest("issuer-and-subject-not-byte-for-byte-equal.pem"); | 209 RunTest("issuer-and-subject-not-byte-for-byte-equal.pem"); |
218 } | 210 } |
219 | 211 |
220 TEST(VerifyCertificateChainTest, IssuerAndSubjectNotByteForByteEqualAnchor) { | 212 TEST(VerifyCertificateChainTest, IssuerAndSubjectNotByteForByteEqualAnchor) { |
221 RunTest("issuer-and-subject-not-byte-for-byte-equal-anchor.pem"); | 213 RunTest("issuer-and-subject-not-byte-for-byte-equal-anchor.pem"); |
222 } | 214 } |
223 | 215 |
| 216 TEST(VerifyCertificateChainTest, ViolatesPathlen1Root) { |
| 217 RunTest("violates-pathlen-1-root.pem"); |
| 218 } |
| 219 |
| 220 TEST(VerifyCertificateChainTest, NonSelfSignedRoot) { |
| 221 RunTest("non-self-signed-root.pem"); |
| 222 } |
| 223 |
224 // Tests that verifying a chain with no certificates fails. | 224 // Tests that verifying a chain with no certificates fails. |
225 TEST(VerifyCertificateChainTest, EmptyChainIsInvalid) { | 225 TEST(VerifyCertificateChainTest, EmptyChainIsInvalid) { |
226 TrustStore trust_store; | 226 TrustStore trust_store; |
227 der::GeneralizedTime time; | 227 der::GeneralizedTime time; |
228 std::vector<der::Input> chain; | 228 std::vector<der::Input> chain; |
229 SimpleSignaturePolicy signature_policy(2048); | 229 SimpleSignaturePolicy signature_policy(2048); |
230 | 230 |
231 ASSERT_FALSE( | 231 ASSERT_FALSE( |
232 VerifyCertificateChain(chain, trust_store, &signature_policy, time)); | 232 VerifyCertificateChain(chain, trust_store, &signature_policy, time)); |
233 } | 233 } |
234 | 234 |
235 // TODO(eroman): Add test that invalidate validity dates where the day or month | 235 // TODO(eroman): Add test that invalidate validity dates where the day or month |
236 // ordinal not in range, like "March 39, 2016" are rejected. | 236 // ordinal not in range, like "March 39, 2016" are rejected. |
237 | 237 |
238 } // namespace | 238 } // namespace |
239 | 239 |
240 } // namespace net | 240 } // namespace net |
OLD | NEW |