| 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 |