| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 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 | 
|  | 3 // found in the LICENSE file. | 
|  | 4 | 
|  | 5 #include "net/cert/internal/verify_certificate_chain.h" | 
|  | 6 | 
|  | 7 #include "base/base_paths.h" | 
|  | 8 #include "base/files/file_util.h" | 
|  | 9 #include "base/path_service.h" | 
|  | 10 #include "base/strings/string_split.h" | 
|  | 11 #include "base/strings/string_util.h" | 
|  | 12 #include "base/strings/stringprintf.h" | 
|  | 13 #include "net/cert/internal/parse_certificate.h" | 
|  | 14 #include "net/cert/internal/signature_policy.h" | 
|  | 15 #include "net/cert/internal/test_helpers.h" | 
|  | 16 #include "net/cert/pem_tokenizer.h" | 
|  | 17 #include "net/der/input.h" | 
|  | 18 #include "testing/gtest/include/gtest/gtest.h" | 
|  | 19 | 
|  | 20 namespace net { | 
|  | 21 | 
|  | 22 namespace { | 
|  | 23 | 
|  | 24 // Reads a data file from the unit-test data. | 
|  | 25 std::string ReadTestFileToString(const std::string& file_name) { | 
|  | 26   // Compute the full path, relative to the src/ directory. | 
|  | 27   base::FilePath src_root; | 
|  | 28   PathService::Get(base::DIR_SOURCE_ROOT, &src_root); | 
|  | 29   base::FilePath filepath = src_root.AppendASCII( | 
|  | 30       std::string("net/data/verify_certificate_chain_unittest/") + file_name); | 
|  | 31 | 
|  | 32   // Read the full contents of the file. | 
|  | 33   std::string file_data; | 
|  | 34   if (!base::ReadFileToString(filepath, &file_data)) { | 
|  | 35     ADD_FAILURE() << "Couldn't read file: " << filepath.value(); | 
|  | 36     return std::string(); | 
|  | 37   } | 
|  | 38 | 
|  | 39   return file_data; | 
|  | 40 } | 
|  | 41 | 
|  | 42 // Adds the certificate |cert_der| as a trusted root in |trust_store|. | 
|  | 43 void AddCertificateToTrustStore(const std::string& cert_der, | 
|  | 44                                 TrustStore* trust_store) { | 
|  | 45   ParsedCertificate cert; | 
|  | 46   ASSERT_TRUE(ParseCertificate(InputFromString(&cert_der), &cert)); | 
|  | 47 | 
|  | 48   ParsedTbsCertificate tbs; | 
|  | 49   ASSERT_TRUE(ParseTbsCertificate(cert.tbs_certificate_tlv, &tbs)); | 
|  | 50   TrustedRoot root = {tbs.spki_tlv.AsString(), tbs.subject_tlv.AsString()}; | 
|  | 51   trust_store->roots.push_back(root); | 
|  | 52 } | 
|  | 53 | 
|  | 54 // Reads a test case from |file_name|. Test cases are comprised of a | 
|  | 55 // certificate chain, trust store, and timestamp to validate at. | 
|  | 56 void ReadTestFromFile(const std::string& file_name, | 
|  | 57                       std::vector<std::string>* chain, | 
|  | 58                       TrustStore* trust_store, | 
|  | 59                       der::GeneralizedTime* time, | 
|  | 60                       bool* verify_result) { | 
|  | 61   chain->clear(); | 
|  | 62   *trust_store = TrustStore(); | 
|  | 63 | 
|  | 64   std::string file_data = ReadTestFileToString(file_name); | 
|  | 65 | 
|  | 66   std::vector<std::string> pem_headers; | 
|  | 67 | 
|  | 68   const char kCertificateHeader[] = "CERTIFICATE"; | 
|  | 69   const char kTrustedCertificateHeader[] = "TRUSTED_CERTIFICATE"; | 
|  | 70   const char kTimeHeader[] = "TIME"; | 
|  | 71   const char kResultHeader[] = "VERIFY_RESULT"; | 
|  | 72 | 
|  | 73   pem_headers.push_back(kCertificateHeader); | 
|  | 74   pem_headers.push_back(kTrustedCertificateHeader); | 
|  | 75   pem_headers.push_back(kTimeHeader); | 
|  | 76   pem_headers.push_back(kResultHeader); | 
|  | 77 | 
|  | 78   bool has_time = false; | 
|  | 79   bool has_result = false; | 
|  | 80 | 
|  | 81   PEMTokenizer pem_tokenizer(file_data, pem_headers); | 
|  | 82   while (pem_tokenizer.GetNext()) { | 
|  | 83     const std::string& block_type = pem_tokenizer.block_type(); | 
|  | 84     const std::string& block_data = pem_tokenizer.data(); | 
|  | 85 | 
|  | 86     if (block_type == kCertificateHeader) { | 
|  | 87       chain->push_back(block_data); | 
|  | 88     } else if (block_type == kTrustedCertificateHeader) { | 
|  | 89       AddCertificateToTrustStore(block_data, trust_store); | 
|  | 90     } else if (block_type == kTimeHeader) { | 
|  | 91       ASSERT_FALSE(has_time) << "Duplicate " << kTimeHeader; | 
|  | 92       has_time = true; | 
|  | 93       ASSERT_TRUE(der::ParseUTCTime(InputFromString(&block_data), time)); | 
|  | 94     } else if (block_type == kResultHeader) { | 
|  | 95       ASSERT_FALSE(has_result) << "Duplicate " << kResultHeader; | 
|  | 96       has_result = true; | 
|  | 97       *verify_result = block_data == "SUCCESS"; | 
|  | 98     } | 
|  | 99   } | 
|  | 100 | 
|  | 101   ASSERT_TRUE(has_time); | 
|  | 102   ASSERT_TRUE(has_result); | 
|  | 103 } | 
|  | 104 | 
|  | 105 void RunTest(const char* file_name) { | 
|  | 106   std::vector<std::string> chain; | 
|  | 107   TrustStore trust_store; | 
|  | 108   der::GeneralizedTime time; | 
|  | 109   bool expected_result; | 
|  | 110 | 
|  | 111   ReadTestFromFile(file_name, &chain, &trust_store, &time, &expected_result); | 
|  | 112 | 
|  | 113   std::vector<der::Input> input_chain; | 
|  | 114   for (const auto& cert_str : chain) | 
|  | 115     input_chain.push_back(InputFromString(&cert_str)); | 
|  | 116 | 
|  | 117   SimpleSignaturePolicy signature_policy(2048); | 
|  | 118 | 
|  | 119   bool result = | 
|  | 120       VerifyCertificateChain(input_chain, trust_store, &signature_policy, time); | 
|  | 121 | 
|  | 122   ASSERT_EQ(expected_result, result); | 
|  | 123 } | 
|  | 124 | 
|  | 125 TEST(VerifyCertificateChainTest, TargetAndIntermediary) { | 
|  | 126   RunTest("target-and-intermediary.pem"); | 
|  | 127 } | 
|  | 128 | 
|  | 129 TEST(VerifyCertificateChainTest, UnknownRoot) { | 
|  | 130   RunTest("unknown-root.pem"); | 
|  | 131 } | 
|  | 132 | 
|  | 133 TEST(VerifyCertificateChainTest, IntermediaryLacksBasicConstraints) { | 
|  | 134   RunTest("intermediary-lacks-basic-constraints.pem"); | 
|  | 135 } | 
|  | 136 | 
|  | 137 TEST(VerifyCertificateChainTest, IntermediaryBasicConstraintsCaFalse) { | 
|  | 138   RunTest("intermediary-basic-constraints-ca-false.pem"); | 
|  | 139 } | 
|  | 140 | 
|  | 141 TEST(VerifyCertificateChainTest, IntermediaryBasicConstraintsNotCritical) { | 
|  | 142   RunTest("intermediary-basic-constraints-not-critical.pem"); | 
|  | 143 } | 
|  | 144 | 
|  | 145 TEST(VerifyCertificateChainTest, IntermediaryLacksSigningKeyUsage) { | 
|  | 146   RunTest("intermediary-lacks-signing-key-usage.pem"); | 
|  | 147 } | 
|  | 148 | 
|  | 149 TEST(VerifyCertificateChainTest, IntermediaryUnknownCriticalExtension) { | 
|  | 150   RunTest("intermediary-unknown-critical-extension.pem"); | 
|  | 151 } | 
|  | 152 | 
|  | 153 TEST(VerifyCertificateChainTest, IntermediaryUnknownNonCriticalExtension) { | 
|  | 154   RunTest("intermediary-unknown-non-critical-extension.pem"); | 
|  | 155 } | 
|  | 156 | 
|  | 157 TEST(VerifyCertificateChainTest, ViolatesBasicConstraintsPathlen0) { | 
|  | 158   RunTest("violates-basic-constraints-pathlen-0.pem"); | 
|  | 159 } | 
|  | 160 | 
|  | 161 TEST(VerifyCertificateChainTest, BasicConstraintsPathlen0SelfIssued) { | 
|  | 162   RunTest("basic-constraints-pathlen-0-self-issued.pem"); | 
|  | 163 } | 
|  | 164 | 
|  | 165 TEST(VerifyCertificateChainTest, TargetSignedWithMd5) { | 
|  | 166   RunTest("target-signed-with-md5.pem"); | 
|  | 167 } | 
|  | 168 | 
|  | 169 TEST(VerifyCertificateChainTest, IntermediarySignedWithMd5) { | 
|  | 170   RunTest("intermediary-signed-with-md5.pem"); | 
|  | 171 } | 
|  | 172 | 
|  | 173 TEST(VerifyCertificateChainTest, TargetWrongSignature) { | 
|  | 174   RunTest("target-wrong-signature.pem"); | 
|  | 175 } | 
|  | 176 | 
|  | 177 TEST(VerifyCertificateChainTest, TargetSignedBy512bitRsa) { | 
|  | 178   RunTest("target-signed-by-512bit-rsa.pem"); | 
|  | 179 } | 
|  | 180 | 
|  | 181 TEST(VerifyCertificateChainTest, TargetSignedUsingEcdsa) { | 
|  | 182   RunTest("target-signed-using-ecdsa.py"); | 
|  | 183 } | 
|  | 184 | 
|  | 185 }  // namespace | 
|  | 186 | 
|  | 187 }  // namespace net | 
| OLD | NEW | 
|---|