1 // Copyright 2016 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/path_builder.h" 6 7 #include "net/base/net_errors.h" 8 #include "net/cert/internal/cert_issuer_source_static.h" 9 #include "net/cert/internal/common_cert_errors.h" 10 #include "net/cert/internal/crl.h" 11 #include "net/cert/internal/parse_certificate.h" 12 #include "net/cert/internal/parsed_certificate.h" 13 #include "net/cert/internal/simple_path_builder_delegate.h" 14 #include "net/cert/internal/trust_store_in_memory.h" 15 #include "net/cert/internal/verify_certificate_chain.h" 16 #include "net/der/encode_values.h" 17 #include "net/der/input.h" 18 #include "third_party/boringssl/src/include/openssl/pool.h" 19 20 #include "net/cert/internal/nist_pkits_unittest.h" 21 22 namespace net { 23 24 namespace { 25 26 class CrlCheckingPathBuilderDelegate : public SimplePathBuilderDelegate { 27 public: CrlCheckingPathBuilderDelegate(const std::vector<std::string> & der_crls,const base::Time & verify_time,const base::TimeDelta & max_age,size_t min_rsa_modulus_length_bits,DigestPolicy digest_policy)28 CrlCheckingPathBuilderDelegate(const std::vector<std::string>& der_crls, 29 const base::Time& verify_time, 30 const base::TimeDelta& max_age, 31 size_t min_rsa_modulus_length_bits, 32 DigestPolicy digest_policy) 33 : SimplePathBuilderDelegate(min_rsa_modulus_length_bits, digest_policy), 34 der_crls_(der_crls), 35 verify_time_(verify_time), 36 max_age_(max_age) {} 37 CheckPathAfterVerification(const CertPathBuilder & path_builder,CertPathBuilderResultPath * path)38 void CheckPathAfterVerification(const CertPathBuilder& path_builder, 39 CertPathBuilderResultPath* path) override { 40 SimplePathBuilderDelegate::CheckPathAfterVerification(path_builder, path); 41 42 if (!path->IsValid()) 43 return; 44 45 // It would be preferable if this test could use 46 // CheckValidatedChainRevocation somehow, but that only supports getting 47 // CRLs by http distributionPoints. So this just settles for writing a 48 // little bit of wrapper code to test CheckCRL directly. 49 const ParsedCertificateList& certs = path->certs; 50 for (size_t reverse_i = 0; reverse_i < certs.size(); ++reverse_i) { 51 size_t i = certs.size() - reverse_i - 1; 52 53 // Trust anchors bypass OCSP/CRL revocation checks. (The only way to 54 // revoke trust anchors is via CRLSet or the built-in SPKI block list). 55 if (reverse_i == 0 && path->last_cert_trust.IsTrustAnchor()) 56 continue; 57 58 // RFC 5280 6.3.3. [If the CRL was not specified in a distribution 59 // point], assume a DP with both the reasons and the 60 // cRLIssuer fields omitted and a distribution point 61 // name of the certificate issuer. 62 // Since this implementation only supports URI names in distribution 63 // points, this means a default-initialized ParsedDistributionPoint is 64 // sufficient. 65 ParsedDistributionPoint fake_cert_dp; 66 ParsedDistributionPoint* cert_dp = &fake_cert_dp; 67 68 // If the target cert does have a distribution point, use it. 69 std::vector<ParsedDistributionPoint> distribution_points; 70 ParsedExtension crl_dp_extension; 71 if (certs[i]->GetExtension(CrlDistributionPointsOid(), 72 &crl_dp_extension)) { 73 ASSERT_TRUE(ParseCrlDistributionPoints(crl_dp_extension.value, 74 &distribution_points)); 75 ASSERT_LE(distribution_points.size(), 1U); 76 if (!distribution_points.empty()) 77 cert_dp = &distribution_points[0]; 78 } 79 80 bool cert_good = false; 81 82 for (const auto& der_crl : der_crls_) { 83 CRLRevocationStatus crl_status = 84 CheckCRL(der_crl, certs, i, *cert_dp, verify_time_, max_age_); 85 if (crl_status == CRLRevocationStatus::REVOKED) { 86 path->errors.GetErrorsForCert(i)->AddError( 87 cert_errors::kCertificateRevoked); 88 return; 89 } 90 if (crl_status == CRLRevocationStatus::GOOD) { 91 cert_good = true; 92 break; 93 } 94 } 95 if (!cert_good) { 96 // PKITS tests assume hard-fail revocation checking. 97 // From PKITS 4.4: "When running the tests in this section, the 98 // application should be configured in such a way that the 99 // certification path is not accepted unless valid, up-to-date 100 // revocation data is available for every certificate in the path." 101 path->errors.GetErrorsForCert(i)->AddError( 102 cert_errors::kUnableToCheckRevocation); 103 } 104 } 105 } 106 107 private: 108 std::vector<std::string> der_crls_; 109 const base::Time verify_time_; 110 const base::TimeDelta max_age_; 111 }; 112 113 class PathBuilderPkitsTestDelegate { 114 public: RunTest(std::vector<std::string> cert_ders,std::vector<std::string> crl_ders,const PkitsTestInfo & orig_info)115 static void RunTest(std::vector<std::string> cert_ders, 116 std::vector<std::string> crl_ders, 117 const PkitsTestInfo& orig_info) { 118 PkitsTestInfo info = orig_info; 119 120 ASSERT_FALSE(cert_ders.empty()); 121 ParsedCertificateList certs; 122 for (const std::string& der : cert_ders) { 123 CertErrors errors; 124 ASSERT_TRUE(ParsedCertificate::CreateAndAddToVector( 125 bssl::UniquePtr<CRYPTO_BUFFER>( 126 CRYPTO_BUFFER_new(reinterpret_cast<const uint8_t*>(der.data()), 127 der.size(), nullptr)), 128 {}, &certs, &errors)) 129 << errors.ToDebugString(); 130 } 131 // First entry in the PKITS chain is the trust anchor. 132 // TODO(mattm): test with all possible trust anchors in the trust store? 133 TrustStoreInMemory trust_store; 134 135 trust_store.AddTrustAnchor(certs[0]); 136 137 // TODO(mattm): test with other irrelevant certs in cert_issuer_sources? 138 CertIssuerSourceStatic cert_issuer_source; 139 for (size_t i = 1; i < cert_ders.size() - 1; ++i) 140 cert_issuer_source.AddCert(certs[i]); 141 142 scoped_refptr<ParsedCertificate> target_cert(certs.back()); 143 144 base::Time verify_time; 145 ASSERT_TRUE(der::GeneralizedTimeToTime(info.time, &verify_time)); 146 CrlCheckingPathBuilderDelegate path_builder_delegate( 147 crl_ders, verify_time, /*max_age=*/base::TimeDelta::FromDays(365 * 2), 148 1024, SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1); 149 150 base::StringPiece test_number = info.test_number; 151 if (test_number == "4.4.19" || test_number == "4.5.3" || 152 test_number == "4.5.4" || test_number == "4.5.6") { 153 // 4.4.19 - fails since CRL is signed by a certificate that is not part 154 // of the verified chain, which is not supported. 155 // 4.5.3 - fails since non-URI distribution point names are not supported 156 // 4.5.4, 4.5.6 - fails since CRL is signed by a certificate that is not 157 // part of verified chain, and also non-URI distribution 158 // point names not supported 159 info.should_validate = false; 160 } else if (test_number == "4.14.1" || test_number == "4.14.4" || 161 test_number == "4.14.5" || test_number == "4.14.7" || 162 test_number == "4.14.18" || test_number == "4.14.19" || 163 test_number == "4.14.22" || test_number == "4.14.24" || 164 test_number == "4.14.25" || test_number == "4.14.28" || 165 test_number == "4.14.29" || test_number == "4.14.30" || 166 test_number == "4.14.33") { 167 // 4.14 tests: 168 // .1 - fails since non-URI distribution point names not supported 169 // .2, .3 - fails since non-URI distribution point names not supported 170 // (but test is expected to fail for other reason) 171 // .4, .5 - fails since non-URI distribution point names not supported, 172 // also uses nameRelativeToCRLIssuer which is not supported 173 // .6 - fails since non-URI distribution point names not supported, also 174 // uses nameRelativeToCRLIssuer which is not supported (but test is 175 // expected to fail for other reason) 176 // .7 - fails since relative distributionPointName not supported 177 // .8, .9 - fails since relative distributionPointName not supported (but 178 // test is expected to fail for other reason) 179 // .10, .11, .12, .13, .14, .27, .35 - PASS 180 // .15, .16, .17, .20, .21 - fails since onlySomeReasons is not supported 181 // (but test is expected to fail for other 182 // reason) 183 // .18, .19 - fails since onlySomeReasons is not supported 184 // .22, .24, .25, .28, .29, .30, .33 - fails since indirect CRLs are not 185 // supported 186 // .23, .26, .31, .32, .34 - fails since indirect CRLs are not supported 187 // (but test is expected to fail for other 188 // reason) 189 info.should_validate = false; 190 } else if (test_number == "4.15.1" || test_number == "4.15.5") { 191 // 4.15 tests: 192 // .1 - fails due to unhandled critical deltaCRLIndicator extension 193 // .2, .3, .6, .7, .8, .9, .10 - PASS since expected cert status is 194 // reflected in base CRL and delta CRL is 195 // ignored 196 // .5 - fails, cert status is "on hold" in base CRL but the delta CRL 197 // which removes the cert from CRL is ignored 198 info.should_validate = false; 199 } else if (test_number == "4.15.4") { 200 // 4.15.4 - Invalid delta-CRL Test4 has the target cert marked revoked in 201 // a delta-CRL. Since delta-CRLs are not supported, the chain validates 202 // successfully. 203 info.should_validate = true; 204 } 205 206 CertPathBuilder path_builder( 207 std::move(target_cert), &trust_store, &path_builder_delegate, info.time, 208 KeyPurpose::ANY_EKU, info.initial_explicit_policy, 209 info.initial_policy_set, info.initial_policy_mapping_inhibit, 210 info.initial_inhibit_any_policy); 211 path_builder.AddCertIssuerSource(&cert_issuer_source); 212 213 CertPathBuilder::Result result = path_builder.Run(); 214 215 if (info.should_validate != result.HasValidPath()) { 216 for (size_t i = 0; i < result.paths.size(); ++i) { 217 const net::CertPathBuilderResultPath* result_path = 218 result.paths[i].get(); 219 LOG(ERROR) << "path " << i << " errors:\n" 220 << result_path->errors.ToDebugString(result_path->certs); 221 } 222 } 223 224 ASSERT_EQ(info.should_validate, result.HasValidPath()); 225 226 if (result.HasValidPath()) { 227 EXPECT_EQ(info.user_constrained_policy_set, 228 result.GetBestValidPath()->user_constrained_policy_set); 229 } 230 } 231 }; 232 233 } // namespace 234 235 INSTANTIATE_TYPED_TEST_SUITE_P(PathBuilder, 236 PkitsTest01SignatureVerification, 237 PathBuilderPkitsTestDelegate); 238 INSTANTIATE_TYPED_TEST_SUITE_P(PathBuilder, 239 PkitsTest02ValidityPeriods, 240 PathBuilderPkitsTestDelegate); 241 INSTANTIATE_TYPED_TEST_SUITE_P(PathBuilder, 242 PkitsTest03VerifyingNameChaining, 243 PathBuilderPkitsTestDelegate); 244 INSTANTIATE_TYPED_TEST_SUITE_P(PathBuilder, 245 PkitsTest04BasicCertificateRevocationTests, 246 PathBuilderPkitsTestDelegate); 247 INSTANTIATE_TYPED_TEST_SUITE_P( 248 PathBuilder, 249 PkitsTest05VerifyingPathswithSelfIssuedCertificates, 250 PathBuilderPkitsTestDelegate); 251 INSTANTIATE_TYPED_TEST_SUITE_P(PathBuilder, 252 PkitsTest06VerifyingBasicConstraints, 253 PathBuilderPkitsTestDelegate); 254 INSTANTIATE_TYPED_TEST_SUITE_P(PathBuilder, 255 PkitsTest07KeyUsage, 256 PathBuilderPkitsTestDelegate); 257 INSTANTIATE_TYPED_TEST_SUITE_P(PathBuilder, 258 PkitsTest08CertificatePolicies, 259 PathBuilderPkitsTestDelegate); 260 INSTANTIATE_TYPED_TEST_SUITE_P(PathBuilder, 261 PkitsTest09RequireExplicitPolicy, 262 PathBuilderPkitsTestDelegate); 263 INSTANTIATE_TYPED_TEST_SUITE_P(PathBuilder, 264 PkitsTest10PolicyMappings, 265 PathBuilderPkitsTestDelegate); 266 INSTANTIATE_TYPED_TEST_SUITE_P(PathBuilder, 267 PkitsTest11InhibitPolicyMapping, 268 PathBuilderPkitsTestDelegate); 269 INSTANTIATE_TYPED_TEST_SUITE_P(PathBuilder, 270 PkitsTest12InhibitAnyPolicy, 271 PathBuilderPkitsTestDelegate); 272 INSTANTIATE_TYPED_TEST_SUITE_P(PathBuilder, 273 PkitsTest13NameConstraints, 274 PathBuilderPkitsTestDelegate); 275 INSTANTIATE_TYPED_TEST_SUITE_P(PathBuilder, 276 PkitsTest14DistributionPoints, 277 PathBuilderPkitsTestDelegate); 278 INSTANTIATE_TYPED_TEST_SUITE_P(PathBuilder, 279 PkitsTest15DeltaCRLs, 280 PathBuilderPkitsTestDelegate); 281 INSTANTIATE_TYPED_TEST_SUITE_P(PathBuilder, 282 PkitsTest16PrivateCertificateExtensions, 283 PathBuilderPkitsTestDelegate); 284 285 } // namespace net 286