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