1 // Copyright 2016 The Chromium Authors
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 "path_builder.h"
6
7 #include <algorithm>
8
9 #include "cert_error_params.h"
10 #include "cert_issuer_source_static.h"
11 #include "common_cert_errors.h"
12 #include "input.h"
13 #include "mock_signature_verify_cache.h"
14 #include "parsed_certificate.h"
15 #include "simple_path_builder_delegate.h"
16 #include "test_helpers.h"
17 #include "trust_store_collection.h"
18 #include "trust_store_in_memory.h"
19 #include "verify_certificate_chain.h"
20
21 #include <gmock/gmock.h>
22 #include <gtest/gtest.h>
23 #include <openssl/pool.h>
24
25 namespace bssl {
26
27 // TODO(crbug.com/634443): Assert the errors for each ResultPath.
28
29 namespace {
30
31 using ::testing::_;
32 using ::testing::Invoke;
33 using ::testing::StrictMock;
34
35 class TestPathBuilderDelegate : public SimplePathBuilderDelegate {
36 public:
TestPathBuilderDelegate(size_t min_rsa_modulus_length_bits,DigestPolicy digest_policy)37 TestPathBuilderDelegate(size_t min_rsa_modulus_length_bits,
38 DigestPolicy digest_policy)
39 : SimplePathBuilderDelegate(min_rsa_modulus_length_bits, digest_policy) {}
40
IsDeadlineExpired()41 bool IsDeadlineExpired() override { return deadline_is_expired_; }
42
SetDeadlineExpiredForTesting(bool deadline_is_expired)43 void SetDeadlineExpiredForTesting(bool deadline_is_expired) {
44 deadline_is_expired_ = deadline_is_expired;
45 }
46
GetVerifyCache()47 SignatureVerifyCache *GetVerifyCache() override {
48 return use_signature_cache_ ? &cache_ : nullptr;
49 }
50
ActivateCache()51 void ActivateCache() { use_signature_cache_ = true; }
52
DeActivateCache()53 void DeActivateCache() { use_signature_cache_ = false; }
54
GetMockVerifyCache()55 MockSignatureVerifyCache *GetMockVerifyCache() { return &cache_; }
56
AllowPrecert()57 void AllowPrecert() { allow_precertificate_ = true; }
58
DisallowPrecert()59 void DisallowPrecert() { allow_precertificate_ = false; }
60
AcceptPreCertificates()61 bool AcceptPreCertificates() override {
62 return allow_precertificate_;
63 }
64
65 private:
66 bool deadline_is_expired_ = false;
67 bool use_signature_cache_ = false;
68 bool allow_precertificate_ = false;
69 MockSignatureVerifyCache cache_;
70 };
71
72 class CertPathBuilderDelegateBase : public SimplePathBuilderDelegate {
73 public:
CertPathBuilderDelegateBase()74 CertPathBuilderDelegateBase()
75 : SimplePathBuilderDelegate(
76 1024, SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1) {}
CheckPathAfterVerification(const CertPathBuilder & path_builder,CertPathBuilderResultPath * path)77 void CheckPathAfterVerification(const CertPathBuilder &path_builder,
78 CertPathBuilderResultPath *path) override {
79 ADD_FAILURE() << "Tests must override this";
80 }
81 };
82
83 class MockPathBuilderDelegate : public CertPathBuilderDelegateBase {
84 public:
85 MOCK_METHOD2(CheckPathAfterVerification,
86 void(const CertPathBuilder &path_builder,
87 CertPathBuilderResultPath *path));
88 };
89
90 // AsyncCertIssuerSourceStatic always returns its certs asynchronously.
91 class AsyncCertIssuerSourceStatic : public CertIssuerSource {
92 public:
93 class StaticAsyncRequest : public Request {
94 public:
StaticAsyncRequest(ParsedCertificateList && issuers)95 explicit StaticAsyncRequest(ParsedCertificateList &&issuers) {
96 issuers_.swap(issuers);
97 issuers_iter_ = issuers_.begin();
98 }
99
100 StaticAsyncRequest(const StaticAsyncRequest &) = delete;
101 StaticAsyncRequest &operator=(const StaticAsyncRequest &) = delete;
102
103 ~StaticAsyncRequest() override = default;
104
GetNext(ParsedCertificateList * out_certs)105 void GetNext(ParsedCertificateList *out_certs) override {
106 if (issuers_iter_ != issuers_.end()) {
107 out_certs->push_back(std::move(*issuers_iter_++));
108 }
109 }
110
111 ParsedCertificateList issuers_;
112 ParsedCertificateList::iterator issuers_iter_;
113 };
114
115 ~AsyncCertIssuerSourceStatic() override = default;
116
SetAsyncGetCallback(std::function<void ()> closure)117 void SetAsyncGetCallback(std::function<void()> closure) {
118 async_get_callback_ = std::move(closure);
119 }
120
AddCert(std::shared_ptr<const ParsedCertificate> cert)121 void AddCert(std::shared_ptr<const ParsedCertificate> cert) {
122 static_cert_issuer_source_.AddCert(std::move(cert));
123 }
124
SyncGetIssuersOf(const ParsedCertificate * cert,ParsedCertificateList * issuers)125 void SyncGetIssuersOf(const ParsedCertificate *cert,
126 ParsedCertificateList *issuers) override {}
AsyncGetIssuersOf(const ParsedCertificate * cert,std::unique_ptr<Request> * out_req)127 void AsyncGetIssuersOf(const ParsedCertificate *cert,
128 std::unique_ptr<Request> *out_req) override {
129 num_async_gets_++;
130 ParsedCertificateList issuers;
131 static_cert_issuer_source_.SyncGetIssuersOf(cert, &issuers);
132 auto req = std::make_unique<StaticAsyncRequest>(std::move(issuers));
133 *out_req = std::move(req);
134 if (async_get_callback_) {
135 async_get_callback_();
136 }
137 }
num_async_gets() const138 int num_async_gets() const { return num_async_gets_; }
139
140 private:
141 CertIssuerSourceStatic static_cert_issuer_source_;
142
143 int num_async_gets_ = 0;
144 std::function<void()> async_get_callback_ = nullptr;
145 };
146
ReadTestPem(const std::string & file_name,const std::string & block_name,std::string * result)147 ::testing::AssertionResult ReadTestPem(const std::string &file_name,
148 const std::string &block_name,
149 std::string *result) {
150 const PemBlockMapping mappings[] = {
151 {block_name.c_str(), result},
152 };
153
154 return ReadTestDataFromPemFile(file_name, mappings);
155 }
156
ReadTestCert(const std::string & file_name,std::shared_ptr<const ParsedCertificate> * result)157 ::testing::AssertionResult ReadTestCert(
158 const std::string &file_name,
159 std::shared_ptr<const ParsedCertificate> *result) {
160 std::string der;
161 ::testing::AssertionResult r = ReadTestPem(
162 "testdata/path_builder_unittest/" + file_name, "CERTIFICATE", &der);
163 if (!r) {
164 return r;
165 }
166 CertErrors errors;
167 *result = ParsedCertificate::Create(
168 bssl::UniquePtr<CRYPTO_BUFFER>(CRYPTO_BUFFER_new(
169 reinterpret_cast<const uint8_t *>(der.data()), der.size(), nullptr)),
170 {}, &errors);
171 if (!*result) {
172 return ::testing::AssertionFailure()
173 << "ParseCertificate::Create() failed:\n"
174 << errors.ToDebugString();
175 }
176 return ::testing::AssertionSuccess();
177 }
178
179 class PathBuilderMultiRootTest : public ::testing::Test {
180 public:
PathBuilderMultiRootTest()181 PathBuilderMultiRootTest()
182 : delegate_(1024, TestPathBuilderDelegate::DigestPolicy::kWeakAllowSha1) {
183 }
184
SetUp()185 void SetUp() override {
186 ASSERT_TRUE(ReadTestCert("multi-root-A-by-B.pem", &a_by_b_));
187 ASSERT_TRUE(ReadTestCert("multi-root-B-by-C.pem", &b_by_c_));
188 ASSERT_TRUE(ReadTestCert("multi-root-B-by-F.pem", &b_by_f_));
189 ASSERT_TRUE(ReadTestCert("multi-root-C-by-D.pem", &c_by_d_));
190 ASSERT_TRUE(ReadTestCert("multi-root-C-by-E.pem", &c_by_e_));
191 ASSERT_TRUE(ReadTestCert("multi-root-D-by-D.pem", &d_by_d_));
192 ASSERT_TRUE(ReadTestCert("multi-root-E-by-E.pem", &e_by_e_));
193 ASSERT_TRUE(ReadTestCert("multi-root-F-by-E.pem", &f_by_e_));
194 }
195
196 protected:
197 std::shared_ptr<const ParsedCertificate> a_by_b_, b_by_c_, b_by_f_, c_by_d_,
198 c_by_e_, d_by_d_, e_by_e_, f_by_e_;
199
200 TestPathBuilderDelegate delegate_;
201 der::GeneralizedTime time_ = {2017, 3, 1, 0, 0, 0};
202
203 const InitialExplicitPolicy initial_explicit_policy_ =
204 InitialExplicitPolicy::kFalse;
205 const std::set<der::Input> user_initial_policy_set_ = {
206 der::Input(kAnyPolicyOid)};
207 const InitialPolicyMappingInhibit initial_policy_mapping_inhibit_ =
208 InitialPolicyMappingInhibit::kFalse;
209 const InitialAnyPolicyInhibit initial_any_policy_inhibit_ =
210 InitialAnyPolicyInhibit::kFalse;
211 };
212
213 // Tests when the target cert has the same name and key as a trust anchor,
214 // however is signed by a different trust anchor. This should successfully build
215 // a path, however the trust anchor will be the signer of this cert.
216 //
217 // (This test is very similar to TestEndEntityHasSameNameAndSpkiAsTrustAnchor
218 // but with different data; also in this test the target cert itself is in the
219 // trust store).
TEST_F(PathBuilderMultiRootTest,TargetHasNameAndSpkiOfTrustAnchor)220 TEST_F(PathBuilderMultiRootTest, TargetHasNameAndSpkiOfTrustAnchor) {
221 TrustStoreInMemory trust_store;
222 trust_store.AddTrustAnchor(a_by_b_);
223 trust_store.AddTrustAnchor(b_by_f_);
224
225 CertPathBuilder path_builder(
226 a_by_b_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
227 initial_explicit_policy_, user_initial_policy_set_,
228 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
229
230 auto result = path_builder.Run();
231
232 ASSERT_TRUE(result.HasValidPath());
233 VerifyError error = result.GetBestPathVerifyError();
234 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_VERIFIED)
235 << error.DiagnosticString();
236 const auto &path = *result.GetBestValidPath();
237 ASSERT_EQ(2U, path.certs.size());
238 EXPECT_EQ(a_by_b_, path.certs[0]);
239 EXPECT_EQ(b_by_f_, path.certs[1]);
240 }
241
242 // If the target cert is has the same name and key as a trust anchor, however
243 // is NOT itself signed by a trust anchor, it fails. Although the provided SPKI
244 // is trusted, the certificate contents cannot be verified.
TEST_F(PathBuilderMultiRootTest,TargetWithSameNameAsTrustAnchorFails)245 TEST_F(PathBuilderMultiRootTest, TargetWithSameNameAsTrustAnchorFails) {
246 TrustStoreInMemory trust_store;
247 trust_store.AddTrustAnchor(a_by_b_);
248
249 CertPathBuilder path_builder(
250 a_by_b_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
251 initial_explicit_policy_, user_initial_policy_set_,
252 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
253
254 auto result = path_builder.Run();
255
256 EXPECT_FALSE(result.HasValidPath());
257 EXPECT_EQ(1U, result.max_depth_seen);
258 VerifyError error = result.GetBestPathVerifyError();
259 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_NOT_FOUND)
260 << error.DiagnosticString();
261 }
262
263 // Test a failed path building when the trust anchor is provided as a
264 // supplemental certificate. Conceptually the following paths could be built:
265 //
266 // B(C) <- C(D) <- [Trust anchor D]
267 // B(C) <- C(D) <- D(D) <- [Trust anchor D]
268 //
269 // However the second one is extraneous given the shorter path.
TEST_F(PathBuilderMultiRootTest,SelfSignedTrustAnchorSupplementalCert)270 TEST_F(PathBuilderMultiRootTest, SelfSignedTrustAnchorSupplementalCert) {
271 TrustStoreInMemory trust_store;
272 trust_store.AddTrustAnchor(d_by_d_);
273
274 // The (extraneous) trust anchor D(D) is supplied as a certificate, as is the
275 // intermediate needed for path building C(D).
276 CertIssuerSourceStatic sync_certs;
277 sync_certs.AddCert(d_by_d_);
278 sync_certs.AddCert(c_by_d_);
279
280 // C(D) is not valid at this time, so path building will fail.
281 der::GeneralizedTime expired_time = {2016, 1, 1, 0, 0, 0};
282
283 CertPathBuilder path_builder(
284 b_by_c_, &trust_store, &delegate_, expired_time, KeyPurpose::ANY_EKU,
285 initial_explicit_policy_, user_initial_policy_set_,
286 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
287 path_builder.AddCertIssuerSource(&sync_certs);
288
289 auto result = path_builder.Run();
290
291 EXPECT_FALSE(result.HasValidPath());
292 ASSERT_EQ(1U, result.paths.size());
293
294 EXPECT_FALSE(result.paths[0]->IsValid());
295 const auto &path0 = *result.paths[0];
296 ASSERT_EQ(3U, path0.certs.size());
297 EXPECT_EQ(b_by_c_, path0.certs[0]);
298 EXPECT_EQ(c_by_d_, path0.certs[1]);
299 EXPECT_EQ(d_by_d_, path0.certs[2]);
300
301 VerifyError error = result.GetBestPathVerifyError();
302 ASSERT_EQ(error.Code(), VerifyError::StatusCode::CERTIFICATE_NOT_YET_VALID)
303 << error.DiagnosticString();
304 }
305
306 // Test verifying a certificate that is a trust anchor.
TEST_F(PathBuilderMultiRootTest,TargetIsSelfSignedTrustAnchor)307 TEST_F(PathBuilderMultiRootTest, TargetIsSelfSignedTrustAnchor) {
308 TrustStoreInMemory trust_store;
309 trust_store.AddTrustAnchor(e_by_e_);
310 // This is not necessary for the test, just an extra...
311 trust_store.AddTrustAnchor(f_by_e_);
312
313 CertPathBuilder path_builder(
314 e_by_e_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
315 initial_explicit_policy_, user_initial_policy_set_,
316 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
317
318 auto result = path_builder.Run();
319
320 ASSERT_TRUE(result.HasValidPath());
321
322 // Verifying a trusted leaf certificate is not permitted, however this
323 // certificate is self-signed, and can chain to itself.
324 const auto &path = *result.GetBestValidPath();
325 ASSERT_EQ(2U, path.certs.size());
326 EXPECT_EQ(e_by_e_, path.certs[0]);
327 EXPECT_EQ(e_by_e_, path.certs[1]);
328
329 VerifyError error = result.GetBestPathVerifyError();
330 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_VERIFIED)
331 << error.DiagnosticString();
332 }
333
334 // If the target cert is directly issued by a trust anchor, it should verify
335 // without any intermediate certs being provided.
TEST_F(PathBuilderMultiRootTest,TargetDirectlySignedByTrustAnchor)336 TEST_F(PathBuilderMultiRootTest, TargetDirectlySignedByTrustAnchor) {
337 TrustStoreInMemory trust_store;
338 trust_store.AddTrustAnchor(b_by_f_);
339
340 CertPathBuilder path_builder(
341 a_by_b_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
342 initial_explicit_policy_, user_initial_policy_set_,
343 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
344
345 auto result = path_builder.Run();
346
347 ASSERT_TRUE(result.HasValidPath());
348 const auto &path = *result.GetBestValidPath();
349 ASSERT_EQ(2U, path.certs.size());
350 EXPECT_EQ(a_by_b_, path.certs[0]);
351 EXPECT_EQ(b_by_f_, path.certs[1]);
352
353 VerifyError error = result.GetBestPathVerifyError();
354 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_VERIFIED)
355 << error.DiagnosticString();
356 }
357
358 // Test that async cert queries are not made if the path can be successfully
359 // built with synchronously available certs.
TEST_F(PathBuilderMultiRootTest,TriesSyncFirst)360 TEST_F(PathBuilderMultiRootTest, TriesSyncFirst) {
361 TrustStoreInMemory trust_store;
362 trust_store.AddTrustAnchor(e_by_e_);
363
364 CertIssuerSourceStatic sync_certs;
365 sync_certs.AddCert(b_by_f_);
366 sync_certs.AddCert(f_by_e_);
367
368 AsyncCertIssuerSourceStatic async_certs;
369 async_certs.AddCert(b_by_c_);
370 async_certs.AddCert(c_by_e_);
371
372 CertPathBuilder path_builder(
373 a_by_b_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
374 initial_explicit_policy_, user_initial_policy_set_,
375 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
376 path_builder.AddCertIssuerSource(&async_certs);
377 path_builder.AddCertIssuerSource(&sync_certs);
378
379 auto result = path_builder.Run();
380
381 EXPECT_TRUE(result.HasValidPath());
382 EXPECT_EQ(0, async_certs.num_async_gets());
383
384 VerifyError error = result.GetBestPathVerifyError();
385 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_VERIFIED)
386 << error.DiagnosticString();
387 }
388
389 // If async queries are needed, all async sources will be queried
390 // simultaneously.
TEST_F(PathBuilderMultiRootTest,TestAsyncSimultaneous)391 TEST_F(PathBuilderMultiRootTest, TestAsyncSimultaneous) {
392 TrustStoreInMemory trust_store;
393 trust_store.AddTrustAnchor(e_by_e_);
394
395 CertIssuerSourceStatic sync_certs;
396 sync_certs.AddCert(b_by_c_);
397 sync_certs.AddCert(b_by_f_);
398
399 AsyncCertIssuerSourceStatic async_certs1;
400 async_certs1.AddCert(c_by_e_);
401
402 AsyncCertIssuerSourceStatic async_certs2;
403 async_certs2.AddCert(f_by_e_);
404
405 CertPathBuilder path_builder(
406 a_by_b_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
407 initial_explicit_policy_, user_initial_policy_set_,
408 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
409 path_builder.AddCertIssuerSource(&async_certs1);
410 path_builder.AddCertIssuerSource(&async_certs2);
411 path_builder.AddCertIssuerSource(&sync_certs);
412
413 auto result = path_builder.Run();
414
415 EXPECT_TRUE(result.HasValidPath());
416 EXPECT_EQ(1, async_certs1.num_async_gets());
417 EXPECT_EQ(1, async_certs2.num_async_gets());
418
419 VerifyError error = result.GetBestPathVerifyError();
420 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_VERIFIED)
421 << error.DiagnosticString();
422 }
423
424 // Test that PathBuilder does not generate longer paths than necessary if one of
425 // the supplied certs is itself a trust anchor.
TEST_F(PathBuilderMultiRootTest,TestLongChain)426 TEST_F(PathBuilderMultiRootTest, TestLongChain) {
427 // Both D(D) and C(D) are trusted roots.
428 TrustStoreInMemory trust_store;
429 trust_store.AddTrustAnchor(d_by_d_);
430 trust_store.AddTrustAnchor(c_by_d_);
431
432 // Certs B(C), and C(D) are all supplied.
433 CertIssuerSourceStatic sync_certs;
434 sync_certs.AddCert(b_by_c_);
435 sync_certs.AddCert(c_by_d_);
436
437 CertPathBuilder path_builder(
438 a_by_b_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
439 initial_explicit_policy_, user_initial_policy_set_,
440 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
441 path_builder.AddCertIssuerSource(&sync_certs);
442
443 auto result = path_builder.Run();
444
445 ASSERT_TRUE(result.HasValidPath());
446
447 // The result path should be A(B) <- B(C) <- C(D)
448 // not the longer but also valid A(B) <- B(C) <- C(D) <- D(D)
449 EXPECT_EQ(3U, result.GetBestValidPath()->certs.size());
450
451 VerifyError error = result.GetBestPathVerifyError();
452 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_VERIFIED)
453 << error.DiagnosticString();
454 }
455
456 // Test that PathBuilder will backtrack and try a different path if the first
457 // one doesn't work out.
TEST_F(PathBuilderMultiRootTest,TestBacktracking)458 TEST_F(PathBuilderMultiRootTest, TestBacktracking) {
459 // Only D(D) is a trusted root.
460 TrustStoreInMemory trust_store;
461 trust_store.AddTrustAnchor(d_by_d_);
462
463 // Certs B(F) and F(E) are supplied synchronously, thus the path
464 // A(B) <- B(F) <- F(E) should be built first, though it won't verify.
465 CertIssuerSourceStatic sync_certs;
466 sync_certs.AddCert(b_by_f_);
467 sync_certs.AddCert(f_by_e_);
468
469 // Certs B(C), and C(D) are supplied asynchronously, so the path
470 // A(B) <- B(C) <- C(D) <- D(D) should be tried second.
471 AsyncCertIssuerSourceStatic async_certs;
472 async_certs.AddCert(b_by_c_);
473 async_certs.AddCert(c_by_d_);
474
475 CertPathBuilder path_builder(
476 a_by_b_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
477 initial_explicit_policy_, user_initial_policy_set_,
478 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
479 path_builder.AddCertIssuerSource(&sync_certs);
480 path_builder.AddCertIssuerSource(&async_certs);
481
482 auto result = path_builder.Run();
483
484 ASSERT_TRUE(result.HasValidPath());
485
486 // The partial path should be returned even though it didn't reach a trust
487 // anchor.
488 ASSERT_EQ(2U, result.paths.size());
489 EXPECT_FALSE(result.paths[0]->IsValid());
490 ASSERT_EQ(3U, result.paths[0]->certs.size());
491 EXPECT_EQ(a_by_b_, result.paths[0]->certs[0]);
492 EXPECT_EQ(b_by_f_, result.paths[0]->certs[1]);
493 EXPECT_EQ(f_by_e_, result.paths[0]->certs[2]);
494
495 // The result path should be A(B) <- B(C) <- C(D) <- D(D)
496 EXPECT_EQ(1U, result.best_result_index);
497 EXPECT_TRUE(result.paths[1]->IsValid());
498 const auto &path = *result.GetBestValidPath();
499 ASSERT_EQ(4U, path.certs.size());
500 EXPECT_EQ(a_by_b_, path.certs[0]);
501 EXPECT_EQ(b_by_c_, path.certs[1]);
502 EXPECT_EQ(c_by_d_, path.certs[2]);
503 EXPECT_EQ(d_by_d_, path.certs[3]);
504
505 VerifyError error = result.GetBestPathVerifyError();
506 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_VERIFIED)
507 << error.DiagnosticString();
508 }
509
510 // Test that if no path to a trust anchor was found, the partial path is
511 // returned.
TEST_F(PathBuilderMultiRootTest,TestOnlyPartialPathResult)512 TEST_F(PathBuilderMultiRootTest, TestOnlyPartialPathResult) {
513 TrustStoreInMemory trust_store;
514
515 // Certs B(F) and F(E) are supplied synchronously, thus the path
516 // A(B) <- B(F) <- F(E) should be built first, though it won't verify.
517 CertIssuerSourceStatic sync_certs;
518 sync_certs.AddCert(b_by_f_);
519 sync_certs.AddCert(f_by_e_);
520
521 CertPathBuilder path_builder(
522 a_by_b_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
523 initial_explicit_policy_, user_initial_policy_set_,
524 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
525 path_builder.AddCertIssuerSource(&sync_certs);
526
527 auto result = path_builder.Run();
528
529 EXPECT_FALSE(result.HasValidPath());
530
531 // The partial path should be returned even though it didn't reach a trust
532 // anchor.
533 ASSERT_EQ(1U, result.paths.size());
534 EXPECT_FALSE(result.paths[0]->IsValid());
535 ASSERT_EQ(3U, result.paths[0]->certs.size());
536 EXPECT_EQ(a_by_b_, result.paths[0]->certs[0]);
537 EXPECT_EQ(b_by_f_, result.paths[0]->certs[1]);
538 EXPECT_EQ(f_by_e_, result.paths[0]->certs[2]);
539
540 VerifyError error = result.GetBestPathVerifyError();
541 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_NOT_FOUND)
542 << error.DiagnosticString();
543 }
544
545 // Test that if two partial paths are returned, the first is marked as the best
546 // path.
TEST_F(PathBuilderMultiRootTest,TestTwoPartialPathResults)547 TEST_F(PathBuilderMultiRootTest, TestTwoPartialPathResults) {
548 TrustStoreInMemory trust_store;
549
550 // Certs B(F) and F(E) are supplied synchronously, thus the path
551 // A(B) <- B(F) <- F(E) should be built first, though it won't verify.
552 CertIssuerSourceStatic sync_certs;
553 sync_certs.AddCert(b_by_f_);
554 sync_certs.AddCert(f_by_e_);
555
556 // Certs B(C), and C(D) are supplied asynchronously, so the path
557 // A(B) <- B(C) <- C(D) <- D(D) should be tried second.
558 AsyncCertIssuerSourceStatic async_certs;
559 async_certs.AddCert(b_by_c_);
560 async_certs.AddCert(c_by_d_);
561
562 CertPathBuilder path_builder(
563 a_by_b_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
564 initial_explicit_policy_, user_initial_policy_set_,
565 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
566 path_builder.AddCertIssuerSource(&sync_certs);
567 path_builder.AddCertIssuerSource(&async_certs);
568
569 auto result = path_builder.Run();
570
571 EXPECT_FALSE(result.HasValidPath());
572
573 // First partial path found should be marked as the best one.
574 EXPECT_EQ(0U, result.best_result_index);
575
576 ASSERT_EQ(2U, result.paths.size());
577 EXPECT_FALSE(result.paths[0]->IsValid());
578 ASSERT_EQ(3U, result.paths[0]->certs.size());
579 EXPECT_EQ(a_by_b_, result.paths[0]->certs[0]);
580 EXPECT_EQ(b_by_f_, result.paths[0]->certs[1]);
581 EXPECT_EQ(f_by_e_, result.paths[0]->certs[2]);
582
583 EXPECT_FALSE(result.paths[1]->IsValid());
584 ASSERT_EQ(3U, result.paths[1]->certs.size());
585 EXPECT_EQ(a_by_b_, result.paths[1]->certs[0]);
586 EXPECT_EQ(b_by_c_, result.paths[1]->certs[1]);
587 EXPECT_EQ(c_by_d_, result.paths[1]->certs[2]);
588
589 VerifyError error = result.GetBestPathVerifyError();
590 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_NOT_FOUND)
591 << error.DiagnosticString();
592 }
593
594 // Test that if no valid path is found, and the first invalid path is a partial
595 // path, but the 2nd invalid path ends with a cert with a trust record, the 2nd
596 // path should be preferred.
TEST_F(PathBuilderMultiRootTest,TestDistrustedPathPreferredOverPartialPath)597 TEST_F(PathBuilderMultiRootTest, TestDistrustedPathPreferredOverPartialPath) {
598 // Only D(D) has a trust record, but it is distrusted.
599 TrustStoreInMemory trust_store;
600 trust_store.AddDistrustedCertificateForTest(d_by_d_);
601
602 // Certs B(F) and F(E) are supplied synchronously, thus the path
603 // A(B) <- B(F) <- F(E) should be built first, though it won't verify.
604 CertIssuerSourceStatic sync_certs;
605 sync_certs.AddCert(b_by_f_);
606 sync_certs.AddCert(f_by_e_);
607
608 // Certs B(C), and C(D) are supplied asynchronously, so the path
609 // A(B) <- B(C) <- C(D) <- D(D) should be tried second.
610 AsyncCertIssuerSourceStatic async_certs;
611 async_certs.AddCert(b_by_c_);
612 async_certs.AddCert(c_by_d_);
613
614 CertPathBuilder path_builder(
615 a_by_b_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
616 initial_explicit_policy_, user_initial_policy_set_,
617 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
618 path_builder.AddCertIssuerSource(&sync_certs);
619 path_builder.AddCertIssuerSource(&async_certs);
620
621 auto result = path_builder.Run();
622
623 EXPECT_FALSE(result.HasValidPath());
624
625 // The partial path should be returned even though it didn't reach a trust
626 // anchor.
627 ASSERT_EQ(2U, result.paths.size());
628 EXPECT_FALSE(result.paths[0]->IsValid());
629 ASSERT_EQ(3U, result.paths[0]->certs.size());
630 EXPECT_EQ(a_by_b_, result.paths[0]->certs[0]);
631 EXPECT_EQ(b_by_f_, result.paths[0]->certs[1]);
632 EXPECT_EQ(f_by_e_, result.paths[0]->certs[2]);
633
634 // The result path should be A(B) <- B(C) <- C(D) <- D(D)
635 EXPECT_EQ(1U, result.best_result_index);
636 EXPECT_FALSE(result.paths[1]->IsValid());
637 const auto &path = *result.GetBestPathPossiblyInvalid();
638 ASSERT_EQ(4U, path.certs.size());
639 EXPECT_EQ(a_by_b_, path.certs[0]);
640 EXPECT_EQ(b_by_c_, path.certs[1]);
641 EXPECT_EQ(c_by_d_, path.certs[2]);
642 EXPECT_EQ(d_by_d_, path.certs[3]);
643
644 VerifyError error = result.GetBestPathVerifyError();
645 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_NOT_FOUND)
646 << error.DiagnosticString();
647 }
648
649 // Test that whichever order CertIssuerSource returns the issuers, the path
650 // building still succeeds.
TEST_F(PathBuilderMultiRootTest,TestCertIssuerOrdering)651 TEST_F(PathBuilderMultiRootTest, TestCertIssuerOrdering) {
652 // Only D(D) is a trusted root.
653 TrustStoreInMemory trust_store;
654 trust_store.AddTrustAnchor(d_by_d_);
655
656 for (bool reverse_order : {false, true}) {
657 SCOPED_TRACE(reverse_order);
658 std::vector<std::shared_ptr<const ParsedCertificate>> certs = {
659 b_by_c_, b_by_f_, f_by_e_, c_by_d_, c_by_e_};
660 CertIssuerSourceStatic sync_certs;
661 if (reverse_order) {
662 for (auto it = certs.rbegin(); it != certs.rend(); ++it) {
663 sync_certs.AddCert(*it);
664 }
665 } else {
666 for (const auto &cert : certs) {
667 sync_certs.AddCert(cert);
668 }
669 }
670
671 CertPathBuilder path_builder(
672 a_by_b_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
673 initial_explicit_policy_, user_initial_policy_set_,
674 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
675 path_builder.AddCertIssuerSource(&sync_certs);
676
677 auto result = path_builder.Run();
678
679 ASSERT_TRUE(result.HasValidPath());
680
681 // The result path should be A(B) <- B(C) <- C(D) <- D(D)
682 const auto &path = *result.GetBestValidPath();
683 ASSERT_EQ(4U, path.certs.size());
684 EXPECT_EQ(a_by_b_, path.certs[0]);
685 EXPECT_EQ(b_by_c_, path.certs[1]);
686 EXPECT_EQ(c_by_d_, path.certs[2]);
687 EXPECT_EQ(d_by_d_, path.certs[3]);
688
689 VerifyError error = result.GetBestPathVerifyError();
690 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_VERIFIED)
691 << error.DiagnosticString();
692 }
693 }
694
TEST_F(PathBuilderMultiRootTest,TestIterationLimit)695 TEST_F(PathBuilderMultiRootTest, TestIterationLimit) {
696 // D(D) is the trust root.
697 TrustStoreInMemory trust_store;
698 trust_store.AddTrustAnchor(d_by_d_);
699
700 // Certs B(C) and C(D) are supplied.
701 CertIssuerSourceStatic sync_certs;
702 sync_certs.AddCert(b_by_c_);
703 sync_certs.AddCert(c_by_d_);
704
705 for (const bool insufficient_limit : {true, false}) {
706 SCOPED_TRACE(insufficient_limit);
707
708 StrictMock<MockPathBuilderDelegate> mock_delegate;
709 // The CheckPathAfterVerification delegate should be called regardless if
710 // the iteration limit is reached.
711 EXPECT_CALL(mock_delegate, CheckPathAfterVerification(_, _));
712
713 CertPathBuilder path_builder(
714 a_by_b_, &trust_store, &mock_delegate, time_, KeyPurpose::ANY_EKU,
715 initial_explicit_policy_, user_initial_policy_set_,
716 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
717 path_builder.AddCertIssuerSource(&sync_certs);
718
719 if (insufficient_limit) {
720 // A limit of one is insufficient to build a path in this case. Therefore
721 // building is expected to fail in this case.
722 path_builder.SetIterationLimit(1);
723 } else {
724 // The other tests in this file exercise the case that |SetIterationLimit|
725 // isn't called. Therefore set a sufficient limit for the path to be
726 // found.
727 path_builder.SetIterationLimit(5);
728 }
729
730 auto result = path_builder.Run();
731
732 EXPECT_EQ(!insufficient_limit, result.HasValidPath());
733 EXPECT_EQ(insufficient_limit, result.exceeded_iteration_limit);
734
735 VerifyError error = result.GetBestPathVerifyError();
736 if (insufficient_limit) {
737 EXPECT_EQ(2U, result.iteration_count);
738 ASSERT_EQ(error.Code(),
739 VerifyError::StatusCode::PATH_ITERATION_COUNT_EXCEEDED)
740 << error.DiagnosticString();
741 } else {
742 EXPECT_EQ(3U, result.iteration_count);
743 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_VERIFIED)
744 << error.DiagnosticString();
745 }
746 }
747 }
748
TEST_F(PathBuilderMultiRootTest,TestTrivialDeadline)749 TEST_F(PathBuilderMultiRootTest, TestTrivialDeadline) {
750 // C(D) is the trust root.
751 TrustStoreInMemory trust_store;
752 trust_store.AddTrustAnchor(c_by_d_);
753
754 // Cert B(C) is supplied.
755 CertIssuerSourceStatic sync_certs;
756 sync_certs.AddCert(b_by_c_);
757
758 for (const bool insufficient_limit : {true, false}) {
759 SCOPED_TRACE(insufficient_limit);
760
761 CertPathBuilder path_builder(
762 a_by_b_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
763 initial_explicit_policy_, user_initial_policy_set_,
764 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
765 path_builder.AddCertIssuerSource(&sync_certs);
766
767 // Make the deadline either expired or not.
768 delegate_.SetDeadlineExpiredForTesting(insufficient_limit);
769
770 auto result = path_builder.Run();
771
772 EXPECT_EQ(!insufficient_limit, result.HasValidPath());
773 EXPECT_EQ(insufficient_limit, result.exceeded_deadline);
774 EXPECT_EQ(delegate_.IsDeadlineExpired(), insufficient_limit);
775
776 if (insufficient_limit) {
777 ASSERT_EQ(1U, result.paths.size());
778 EXPECT_FALSE(result.paths[0]->IsValid());
779 ASSERT_EQ(1U, result.paths[0]->certs.size());
780 EXPECT_EQ(a_by_b_, result.paths[0]->certs[0]);
781 EXPECT_TRUE(result.paths[0]->errors.ContainsError(
782 cert_errors::kDeadlineExceeded));
783 } else {
784 ASSERT_EQ(1U, result.paths.size());
785 EXPECT_TRUE(result.paths[0]->IsValid());
786 ASSERT_EQ(3U, result.paths[0]->certs.size());
787 EXPECT_EQ(a_by_b_, result.paths[0]->certs[0]);
788 EXPECT_EQ(b_by_c_, result.paths[0]->certs[1]);
789 EXPECT_EQ(c_by_d_, result.paths[0]->certs[2]);
790 }
791 }
792 }
793
TEST_F(PathBuilderMultiRootTest,TestVerifyCache)794 TEST_F(PathBuilderMultiRootTest, TestVerifyCache) {
795 // C(D) is the trust root.
796 TrustStoreInMemory trust_store;
797 trust_store.AddTrustAnchor(c_by_d_);
798
799 // Cert B(C) is supplied.
800 CertIssuerSourceStatic sync_certs;
801 sync_certs.AddCert(b_by_c_);
802
803 // Test Activation / DeActivation of the cache.
804 EXPECT_FALSE(delegate_.GetVerifyCache());
805 delegate_.ActivateCache();
806 EXPECT_TRUE(delegate_.GetVerifyCache());
807 delegate_.DeActivateCache();
808 EXPECT_FALSE(delegate_.GetVerifyCache());
809 delegate_.ActivateCache();
810 EXPECT_TRUE(delegate_.GetVerifyCache());
811 for (size_t i = 0; i < 3; i++) {
812 SCOPED_TRACE(i);
813
814 CertPathBuilder path_builder(
815 a_by_b_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
816 initial_explicit_policy_, user_initial_policy_set_,
817 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
818 path_builder.AddCertIssuerSource(&sync_certs);
819
820 auto result = path_builder.Run();
821
822 ASSERT_EQ(1U, result.paths.size());
823 EXPECT_TRUE(result.paths[0]->IsValid());
824 ASSERT_EQ(3U, result.paths[0]->certs.size());
825 EXPECT_EQ(a_by_b_, result.paths[0]->certs[0]);
826 EXPECT_EQ(b_by_c_, result.paths[0]->certs[1]);
827 EXPECT_EQ(c_by_d_, result.paths[0]->certs[2]);
828
829 // The path is 3 certificates long, so requires 2 distinct signature
830 // verifications. The first time through the loop will cause 2 cache misses
831 // and stores, subsequent iterations will repeat the same verifications,
832 // causing 2 cache hits.
833 EXPECT_EQ(delegate_.GetMockVerifyCache()->CacheHits(), i * 2);
834 EXPECT_EQ(delegate_.GetMockVerifyCache()->CacheMisses(), 2U);
835 EXPECT_EQ(delegate_.GetMockVerifyCache()->CacheStores(), 2U);
836
837 VerifyError error = result.GetBestPathVerifyError();
838 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_VERIFIED)
839 << error.DiagnosticString();
840 }
841 }
842
TEST_F(PathBuilderMultiRootTest,TestDeadline)843 TEST_F(PathBuilderMultiRootTest, TestDeadline) {
844 TrustStoreInMemory trust_store;
845 trust_store.AddTrustAnchor(d_by_d_);
846
847 // Cert B(C) is supplied statically.
848 CertIssuerSourceStatic sync_certs;
849 sync_certs.AddCert(b_by_c_);
850
851 // Cert C(D) is supplied asynchronously and will expire the deadline before
852 // returning the async result.
853 AsyncCertIssuerSourceStatic async_certs;
854 async_certs.AddCert(c_by_d_);
855 async_certs.SetAsyncGetCallback(
856 [&] { delegate_.SetDeadlineExpiredForTesting(true); });
857
858 CertPathBuilder path_builder(
859 a_by_b_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
860 initial_explicit_policy_, user_initial_policy_set_,
861 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
862 path_builder.AddCertIssuerSource(&sync_certs);
863 path_builder.AddCertIssuerSource(&async_certs);
864
865 auto result = path_builder.Run();
866
867 EXPECT_FALSE(result.HasValidPath());
868 EXPECT_TRUE(result.exceeded_deadline);
869 EXPECT_TRUE(delegate_.IsDeadlineExpired());
870
871 // The chain returned should end in c_by_d_, since the deadline would only be
872 // checked again after the async results had been checked (since
873 // AsyncCertIssuerSourceStatic makes the async results available immediately.)
874 ASSERT_EQ(1U, result.paths.size());
875 EXPECT_FALSE(result.paths[0]->IsValid());
876 ASSERT_EQ(3U, result.paths[0]->certs.size());
877 EXPECT_EQ(a_by_b_, result.paths[0]->certs[0]);
878 EXPECT_EQ(b_by_c_, result.paths[0]->certs[1]);
879 EXPECT_EQ(c_by_d_, result.paths[0]->certs[2]);
880 EXPECT_TRUE(
881 result.paths[0]->errors.ContainsError(cert_errors::kDeadlineExceeded));
882
883 VerifyError error = result.GetBestPathVerifyError();
884 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_DEADLINE_EXCEEDED)
885 << error.DiagnosticString();
886 }
887
TEST_F(PathBuilderMultiRootTest,TestDepthLimit)888 TEST_F(PathBuilderMultiRootTest, TestDepthLimit) {
889 // D(D) is the trust root.
890 TrustStoreInMemory trust_store;
891 trust_store.AddTrustAnchor(d_by_d_);
892
893 // Certs B(C) and C(D) are supplied.
894 CertIssuerSourceStatic sync_certs;
895 sync_certs.AddCert(b_by_c_);
896 sync_certs.AddCert(c_by_d_);
897
898 for (const bool insufficient_limit : {true, false}) {
899 CertPathBuilder path_builder(
900 a_by_b_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
901 initial_explicit_policy_, user_initial_policy_set_,
902 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
903 path_builder.AddCertIssuerSource(&sync_certs);
904
905 if (insufficient_limit) {
906 // A limit of depth equal to 2 is insufficient to build the path.
907 // Therefore, building is expected to fail.
908 path_builder.SetDepthLimit(2);
909 } else {
910 // The other tests in this file exercise the case that |SetDepthLimit|
911 // isn't called. Therefore, set a sufficient limit for the path to be
912 // found.
913 path_builder.SetDepthLimit(5);
914 }
915
916 auto result = path_builder.Run();
917
918 EXPECT_EQ(!insufficient_limit, result.HasValidPath());
919 EXPECT_EQ(insufficient_limit,
920 result.AnyPathContainsError(cert_errors::kDepthLimitExceeded));
921 VerifyError error = result.GetBestPathVerifyError();
922 if (insufficient_limit) {
923 EXPECT_EQ(2U, result.max_depth_seen);
924 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_DEPTH_LIMIT_REACHED)
925 << error.DiagnosticString();
926 } else {
927 EXPECT_EQ(4U, result.max_depth_seen);
928 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_VERIFIED)
929 << error.DiagnosticString();
930 }
931 }
932 }
933
TEST_F(PathBuilderMultiRootTest,TestDepthLimitMultiplePaths)934 TEST_F(PathBuilderMultiRootTest, TestDepthLimitMultiplePaths) {
935 // This case tests path building backtracking due to reaching the path depth
936 // limit. Given the root and issuer certificates below, there can be two paths
937 // from between the leaf to a trusted root, one has length of 3 and the other
938 // has length of 4. These certificates are specifically chosen because path
939 // building will first explore the 4-certificate long path then the
940 // 3-certificate long path. So with a depth limit of 3, we can test the
941 // backtracking code path.
942
943 // E(E) and C(D) are the trust roots.
944 TrustStoreInMemory trust_store;
945 trust_store.AddTrustAnchor(e_by_e_);
946 trust_store.AddTrustAnchor(c_by_d_);
947
948 // Certs B(C). B(F) and F(E) are supplied.
949 CertIssuerSourceStatic sync_certs;
950 sync_certs.AddCert(b_by_c_);
951 sync_certs.AddCert(b_by_f_);
952 sync_certs.AddCert(f_by_e_);
953
954 CertPathBuilder path_builder(
955 a_by_b_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
956 initial_explicit_policy_, user_initial_policy_set_,
957 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
958 path_builder.AddCertIssuerSource(&sync_certs);
959
960 path_builder.SetDepthLimit(3);
961
962 auto result = path_builder.Run();
963
964 EXPECT_TRUE(result.HasValidPath());
965 EXPECT_TRUE(result.AnyPathContainsError(cert_errors::kDepthLimitExceeded));
966
967 ASSERT_EQ(result.paths.size(), 2u);
968
969 const CertPathBuilderResultPath *truncated_path = result.paths[0].get();
970 EXPECT_FALSE(truncated_path->IsValid());
971 EXPECT_TRUE(
972 truncated_path->errors.ContainsError(cert_errors::kDepthLimitExceeded));
973 ASSERT_EQ(truncated_path->certs.size(), 3u);
974 EXPECT_EQ(a_by_b_, truncated_path->certs[0]);
975 EXPECT_EQ(b_by_f_, truncated_path->certs[1]);
976 EXPECT_EQ(f_by_e_, truncated_path->certs[2]);
977
978 const CertPathBuilderResultPath *valid_path = result.paths[1].get();
979 EXPECT_TRUE(valid_path->IsValid());
980 EXPECT_FALSE(
981 valid_path->errors.ContainsError(cert_errors::kDepthLimitExceeded));
982 ASSERT_EQ(valid_path->certs.size(), 3u);
983 EXPECT_EQ(a_by_b_, valid_path->certs[0]);
984 EXPECT_EQ(b_by_c_, valid_path->certs[1]);
985 EXPECT_EQ(c_by_d_, valid_path->certs[2]);
986
987 VerifyError error = result.GetBestPathVerifyError();
988 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_VERIFIED)
989 << error.DiagnosticString();
990 }
991
TEST_F(PathBuilderMultiRootTest,TestPreCertificate)992 TEST_F(PathBuilderMultiRootTest, TestPreCertificate) {
993
994 std::string test_dir =
995 "testdata/path_builder_unittest/precertificate/";
996 std::shared_ptr<const ParsedCertificate> root1 =
997 ReadCertFromFile(test_dir + "root.pem");
998 ASSERT_TRUE(root1);
999 std::shared_ptr<const ParsedCertificate> target =
1000 ReadCertFromFile(test_dir + "precertificate.pem");
1001 ASSERT_TRUE(target);
1002
1003 der::GeneralizedTime precert_time = {2023, 10, 1, 0, 0, 0};
1004
1005 TrustStoreInMemory trust_store;
1006 trust_store.AddTrustAnchor(root1);
1007
1008 // PreCertificate should be rejected by default.
1009 EXPECT_FALSE(delegate_.AcceptPreCertificates());
1010 CertPathBuilder path_builder(
1011 target, &trust_store, &delegate_, precert_time, KeyPurpose::ANY_EKU,
1012 initial_explicit_policy_, user_initial_policy_set_,
1013 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
1014 auto result = path_builder.Run();
1015 ASSERT_EQ(1U, result.paths.size());
1016 ASSERT_FALSE(result.paths[0]->IsValid())
1017 << result.paths[0]->errors.ToDebugString(result.paths[0]->certs);
1018 VerifyError error = result.GetBestPathVerifyError();
1019 ASSERT_EQ(error.Code(), VerifyError::StatusCode::CERTIFICATE_INVALID)
1020 << error.DiagnosticString();
1021
1022
1023 // PreCertificate should be accepted if configured.
1024 delegate_.AllowPrecert();
1025 EXPECT_TRUE(delegate_.AcceptPreCertificates());
1026 CertPathBuilder path_builder2(
1027 target, &trust_store, &delegate_, precert_time, KeyPurpose::ANY_EKU,
1028 initial_explicit_policy_, user_initial_policy_set_,
1029 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
1030 auto result2 = path_builder2.Run();
1031 ASSERT_EQ(1U, result2.paths.size());
1032 ASSERT_TRUE(result2.paths[0]->IsValid())
1033 << result2.paths[0]->errors.ToDebugString(result.paths[0]->certs);
1034 VerifyError error2 = result2.GetBestPathVerifyError();
1035 ASSERT_EQ(error2.Code(), VerifyError::StatusCode::PATH_VERIFIED)
1036 << error2.DiagnosticString();
1037 }
1038
1039 class PathBuilderKeyRolloverTest : public ::testing::Test {
1040 public:
PathBuilderKeyRolloverTest()1041 PathBuilderKeyRolloverTest()
1042 : delegate_(1024,
1043 SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1) {}
1044
SetUp()1045 void SetUp() override {
1046 ParsedCertificateList path;
1047
1048 VerifyCertChainTest test;
1049 ASSERT_TRUE(ReadVerifyCertChainTestFromFile(
1050 "testdata/verify_certificate_chain_unittest/key-rollover/oldchain.test",
1051 &test));
1052 path = test.chain;
1053 ASSERT_EQ(3U, path.size());
1054 target_ = path[0];
1055 oldintermediate_ = path[1];
1056 oldroot_ = path[2];
1057 time_ = test.time;
1058
1059 ASSERT_TRUE(target_);
1060 ASSERT_TRUE(oldintermediate_);
1061
1062 ASSERT_TRUE(ReadVerifyCertChainTestFromFile(
1063 "testdata/verify_certificate_chain_unittest/"
1064 "key-rollover/longrolloverchain.test",
1065 &test));
1066 path = test.chain;
1067
1068 ASSERT_EQ(5U, path.size());
1069 newintermediate_ = path[1];
1070 newroot_ = path[2];
1071 newrootrollover_ = path[3];
1072 ASSERT_TRUE(newintermediate_);
1073 ASSERT_TRUE(newroot_);
1074 ASSERT_TRUE(newrootrollover_);
1075 }
1076
1077 protected:
1078 // oldroot-------->newrootrollover newroot
1079 // | | |
1080 // v v v
1081 // oldintermediate newintermediate
1082 // | |
1083 // +------------+-------------+
1084 // |
1085 // v
1086 // target
1087 std::shared_ptr<const ParsedCertificate> target_;
1088 std::shared_ptr<const ParsedCertificate> oldintermediate_;
1089 std::shared_ptr<const ParsedCertificate> newintermediate_;
1090 std::shared_ptr<const ParsedCertificate> oldroot_;
1091 std::shared_ptr<const ParsedCertificate> newroot_;
1092 std::shared_ptr<const ParsedCertificate> newrootrollover_;
1093
1094 SimplePathBuilderDelegate delegate_;
1095 der::GeneralizedTime time_;
1096
1097 const InitialExplicitPolicy initial_explicit_policy_ =
1098 InitialExplicitPolicy::kFalse;
1099 const std::set<der::Input> user_initial_policy_set_ = {
1100 der::Input(kAnyPolicyOid)};
1101 const InitialPolicyMappingInhibit initial_policy_mapping_inhibit_ =
1102 InitialPolicyMappingInhibit::kFalse;
1103 const InitialAnyPolicyInhibit initial_any_policy_inhibit_ =
1104 InitialAnyPolicyInhibit::kFalse;
1105 };
1106
1107 // Tests that if only the old root cert is trusted, the path builder can build a
1108 // path through the new intermediate and rollover cert to the old root.
TEST_F(PathBuilderKeyRolloverTest,TestRolloverOnlyOldRootTrusted)1109 TEST_F(PathBuilderKeyRolloverTest, TestRolloverOnlyOldRootTrusted) {
1110 // Only oldroot is trusted.
1111 TrustStoreInMemory trust_store;
1112 trust_store.AddTrustAnchor(oldroot_);
1113
1114 // Old intermediate cert is not provided, so the pathbuilder will need to go
1115 // through the rollover cert.
1116 CertIssuerSourceStatic sync_certs;
1117 sync_certs.AddCert(newintermediate_);
1118 sync_certs.AddCert(newrootrollover_);
1119
1120 CertPathBuilder path_builder(
1121 target_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
1122 initial_explicit_policy_, user_initial_policy_set_,
1123 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
1124 path_builder.AddCertIssuerSource(&sync_certs);
1125
1126 auto result = path_builder.Run();
1127
1128 EXPECT_TRUE(result.HasValidPath());
1129
1130 // Due to authorityKeyIdentifier prioritization, path builder will first
1131 // attempt: target <- newintermediate <- newrootrollover <- oldroot
1132 // which will succeed.
1133 ASSERT_EQ(1U, result.paths.size());
1134 const auto &path0 = *result.paths[0];
1135 EXPECT_EQ(0U, result.best_result_index);
1136 EXPECT_TRUE(path0.IsValid());
1137 ASSERT_EQ(4U, path0.certs.size());
1138 EXPECT_EQ(target_, path0.certs[0]);
1139 EXPECT_EQ(newintermediate_, path0.certs[1]);
1140 EXPECT_EQ(newrootrollover_, path0.certs[2]);
1141 EXPECT_EQ(oldroot_, path0.certs[3]);
1142
1143 VerifyError error = result.GetBestPathVerifyError();
1144 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_VERIFIED)
1145 << error.DiagnosticString();
1146 }
1147
1148 // Tests that if both old and new roots are trusted it builds a path through
1149 // the new intermediate.
TEST_F(PathBuilderKeyRolloverTest,TestRolloverBothRootsTrusted)1150 TEST_F(PathBuilderKeyRolloverTest, TestRolloverBothRootsTrusted) {
1151 // Both oldroot and newroot are trusted.
1152 TrustStoreInMemory trust_store;
1153 trust_store.AddTrustAnchor(oldroot_);
1154 trust_store.AddTrustAnchor(newroot_);
1155
1156 // Both old and new intermediates + rollover cert are provided.
1157 CertIssuerSourceStatic sync_certs;
1158 sync_certs.AddCert(oldintermediate_);
1159 sync_certs.AddCert(newintermediate_);
1160 sync_certs.AddCert(newrootrollover_);
1161
1162 CertPathBuilder path_builder(
1163 target_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
1164 initial_explicit_policy_, user_initial_policy_set_,
1165 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
1166 path_builder.AddCertIssuerSource(&sync_certs);
1167
1168 auto result = path_builder.Run();
1169
1170 EXPECT_TRUE(result.HasValidPath());
1171
1172 ASSERT_EQ(1U, result.paths.size());
1173 const auto &path = *result.paths[0];
1174 EXPECT_TRUE(result.paths[0]->IsValid());
1175 ASSERT_EQ(3U, path.certs.size());
1176 EXPECT_EQ(target_, path.certs[0]);
1177 // The newer intermediate should be used as newer certs are prioritized in
1178 // path building.
1179 EXPECT_EQ(newintermediate_, path.certs[1]);
1180 EXPECT_EQ(newroot_, path.certs[2]);
1181
1182 VerifyError error = result.GetBestPathVerifyError();
1183 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_VERIFIED)
1184 << error.DiagnosticString();
1185 }
1186
1187 // If trust anchor query returned no results, and there are no issuer
1188 // sources, path building should fail at that point.
TEST_F(PathBuilderKeyRolloverTest,TestAnchorsNoMatchAndNoIssuerSources)1189 TEST_F(PathBuilderKeyRolloverTest, TestAnchorsNoMatchAndNoIssuerSources) {
1190 TrustStoreInMemory trust_store;
1191 trust_store.AddTrustAnchor(newroot_);
1192
1193 CertPathBuilder path_builder(
1194 target_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
1195 initial_explicit_policy_, user_initial_policy_set_,
1196 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
1197
1198 auto result = path_builder.Run();
1199
1200 EXPECT_FALSE(result.HasValidPath());
1201
1202 ASSERT_EQ(1U, result.paths.size());
1203 const auto &path = *result.paths[0];
1204 EXPECT_FALSE(result.paths[0]->IsValid());
1205 ASSERT_EQ(1U, path.certs.size());
1206 EXPECT_EQ(target_, path.certs[0]);
1207
1208 VerifyError error = result.GetBestPathVerifyError();
1209 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_NOT_FOUND)
1210 << error.DiagnosticString();
1211 }
1212
1213 // If a path to a trust anchor could not be found, and the last issuer(s) in
1214 // the chain were culled by the loop checker, the partial path up to that point
1215 // should be returned.
TEST_F(PathBuilderKeyRolloverTest,TestReturnsPartialPathEndedByLoopChecker)1216 TEST_F(PathBuilderKeyRolloverTest, TestReturnsPartialPathEndedByLoopChecker) {
1217 TrustStoreInMemory trust_store;
1218
1219 CertIssuerSourceStatic sync_certs;
1220 sync_certs.AddCert(newintermediate_);
1221 sync_certs.AddCert(newroot_);
1222
1223 CertIssuerSourceStatic rollover_certs;
1224 rollover_certs.AddCert(newrootrollover_);
1225
1226 CertPathBuilder path_builder(
1227 target_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
1228 initial_explicit_policy_, user_initial_policy_set_,
1229 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
1230 path_builder.AddCertIssuerSource(&sync_certs);
1231 // The rollover root is added as a second issuer source to ensure we get paths
1232 // back in a deterministic order, otherwise newroot and newrootrollover do not
1233 // differ in any way that the path builder would use for prioritizing which
1234 // path comes back first.
1235 path_builder.AddCertIssuerSource(&rollover_certs);
1236
1237 auto result = path_builder.Run();
1238
1239 EXPECT_FALSE(result.HasValidPath());
1240 ASSERT_EQ(2U, result.paths.size());
1241
1242 // Since none of the certs are trusted, the path builder should build 4
1243 // candidate paths, all of which are disallowed due to the loop checker:
1244 // target->newintermediate->newroot->newroot
1245 // target->newintermediate->newroot->newrootrollover
1246 // target->newintermediate->newrootrollover->newroot
1247 // target->newintermediate->newrootrollover->newrootrollover
1248 // This should end up returning the 2 partial paths which are the longest
1249 // paths for which no acceptable issuers could be found:
1250 // target->newintermediate->newroot
1251 // target->newintermediate->newrootrollover
1252
1253 {
1254 const auto &path = *result.paths[0];
1255 EXPECT_FALSE(path.IsValid());
1256 ASSERT_EQ(3U, path.certs.size());
1257 EXPECT_EQ(target_, path.certs[0]);
1258 EXPECT_EQ(newintermediate_, path.certs[1]);
1259 EXPECT_EQ(newroot_, path.certs[2]);
1260 EXPECT_TRUE(path.errors.ContainsError(cert_errors::kNoIssuersFound));
1261 }
1262
1263 {
1264 const auto &path = *result.paths[1];
1265 EXPECT_FALSE(path.IsValid());
1266 ASSERT_EQ(3U, path.certs.size());
1267 EXPECT_EQ(target_, path.certs[0]);
1268 EXPECT_EQ(newintermediate_, path.certs[1]);
1269 EXPECT_EQ(newrootrollover_, path.certs[2]);
1270 EXPECT_TRUE(path.errors.ContainsError(cert_errors::kNoIssuersFound));
1271 }
1272
1273 VerifyError error = result.GetBestPathVerifyError();
1274 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_NOT_FOUND)
1275 << error.DiagnosticString();
1276 }
1277
1278 // Tests that multiple trust root matches on a single path will be considered.
1279 // Both roots have the same subject but different keys. Only one of them will
1280 // verify.
TEST_F(PathBuilderKeyRolloverTest,TestMultipleRootMatchesOnlyOneWorks)1281 TEST_F(PathBuilderKeyRolloverTest, TestMultipleRootMatchesOnlyOneWorks) {
1282 TrustStoreCollection trust_store_collection;
1283 TrustStoreInMemory trust_store1;
1284 TrustStoreInMemory trust_store2;
1285 trust_store_collection.AddTrustStore(&trust_store1);
1286 trust_store_collection.AddTrustStore(&trust_store2);
1287 // Add two trust anchors (newroot_ and oldroot_). Path building will attempt
1288 // them in this same order, as trust_store1 was added to
1289 // trust_store_collection first.
1290 trust_store1.AddTrustAnchor(newroot_);
1291 trust_store2.AddTrustAnchor(oldroot_);
1292
1293 // Only oldintermediate is supplied, so the path with newroot should fail,
1294 // oldroot should succeed.
1295 CertIssuerSourceStatic sync_certs;
1296 sync_certs.AddCert(oldintermediate_);
1297
1298 CertPathBuilder path_builder(
1299 target_, &trust_store_collection, &delegate_, time_, KeyPurpose::ANY_EKU,
1300 initial_explicit_policy_, user_initial_policy_set_,
1301 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
1302 path_builder.AddCertIssuerSource(&sync_certs);
1303
1304 auto result = path_builder.Run();
1305
1306 EXPECT_TRUE(result.HasValidPath());
1307 ASSERT_EQ(1U, result.paths.size());
1308
1309 // Due to authorityKeyIdentifier prioritization, path builder will first
1310 // attempt: target <- old intermediate <- oldroot
1311 // which should succeed.
1312 EXPECT_TRUE(result.paths[result.best_result_index]->IsValid());
1313 const auto &path = *result.paths[result.best_result_index];
1314 ASSERT_EQ(3U, path.certs.size());
1315 EXPECT_EQ(target_, path.certs[0]);
1316 EXPECT_EQ(oldintermediate_, path.certs[1]);
1317 EXPECT_EQ(oldroot_, path.certs[2]);
1318
1319 VerifyError error = result.GetBestPathVerifyError();
1320 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_VERIFIED)
1321 << error.DiagnosticString();
1322 }
1323
1324 // Tests that the path builder doesn't build longer than necessary paths,
1325 // by skipping certs where the same Name+SAN+SPKI is already in the current
1326 // path.
TEST_F(PathBuilderKeyRolloverTest,TestRolloverLongChain)1327 TEST_F(PathBuilderKeyRolloverTest, TestRolloverLongChain) {
1328 // Only oldroot is trusted.
1329 TrustStoreInMemory trust_store;
1330 trust_store.AddTrustAnchor(oldroot_);
1331
1332 // New intermediate and new root are provided synchronously.
1333 CertIssuerSourceStatic sync_certs;
1334 sync_certs.AddCert(newintermediate_);
1335 sync_certs.AddCert(newroot_);
1336
1337 // Rollover cert is only provided asynchronously. This will force the
1338 // pathbuilder to first try building a longer than necessary path.
1339 AsyncCertIssuerSourceStatic async_certs;
1340 async_certs.AddCert(newrootrollover_);
1341
1342 CertPathBuilder path_builder(
1343 target_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
1344 initial_explicit_policy_, user_initial_policy_set_,
1345 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
1346 path_builder.AddCertIssuerSource(&sync_certs);
1347 path_builder.AddCertIssuerSource(&async_certs);
1348
1349 auto result = path_builder.Run();
1350
1351 EXPECT_TRUE(result.HasValidPath());
1352 ASSERT_EQ(3U, result.paths.size());
1353
1354 // Path builder will first attempt:
1355 // target <- newintermediate <- newroot <- oldroot
1356 // but it will fail since newroot is self-signed.
1357 EXPECT_FALSE(result.paths[0]->IsValid());
1358 const auto &path0 = *result.paths[0];
1359 ASSERT_EQ(4U, path0.certs.size());
1360 EXPECT_EQ(target_, path0.certs[0]);
1361 EXPECT_EQ(newintermediate_, path0.certs[1]);
1362 EXPECT_EQ(newroot_, path0.certs[2]);
1363 EXPECT_EQ(oldroot_, path0.certs[3]);
1364
1365 // Path builder will next attempt: target <- newintermediate <- oldroot
1366 // but it will fail since newintermediate is signed by newroot.
1367 EXPECT_FALSE(result.paths[1]->IsValid());
1368 const auto &path1 = *result.paths[1];
1369 ASSERT_EQ(3U, path1.certs.size());
1370 EXPECT_EQ(target_, path1.certs[0]);
1371 EXPECT_EQ(newintermediate_, path1.certs[1]);
1372 EXPECT_EQ(oldroot_, path1.certs[2]);
1373
1374 // Path builder will skip:
1375 // target <- newintermediate <- newroot <- newrootrollover <- ...
1376 // Since newroot and newrootrollover have the same Name+SAN+SPKI.
1377
1378 // Finally path builder will use:
1379 // target <- newintermediate <- newrootrollover <- oldroot
1380 EXPECT_EQ(2U, result.best_result_index);
1381 EXPECT_TRUE(result.paths[2]->IsValid());
1382 const auto &path2 = *result.paths[2];
1383 ASSERT_EQ(4U, path2.certs.size());
1384 EXPECT_EQ(target_, path2.certs[0]);
1385 EXPECT_EQ(newintermediate_, path2.certs[1]);
1386 EXPECT_EQ(newrootrollover_, path2.certs[2]);
1387 EXPECT_EQ(oldroot_, path2.certs[3]);
1388
1389 VerifyError error = result.GetBestPathVerifyError();
1390 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_VERIFIED)
1391 << error.DiagnosticString();
1392 }
1393
1394 // Tests that when SetExploreAllPaths is combined with SetIterationLimit the
1395 // path builder will return all the paths that were able to be built before the
1396 // iteration limit was reached.
TEST_F(PathBuilderKeyRolloverTest,ExploreAllPathsWithIterationLimit)1397 TEST_F(PathBuilderKeyRolloverTest, ExploreAllPathsWithIterationLimit) {
1398 struct Expectation {
1399 int iteration_limit;
1400 size_t expected_num_paths;
1401 std::vector<std::shared_ptr<const ParsedCertificate>> partial_path;
1402 } kExpectations[] = {
1403 // No iteration limit. All possible paths should be built.
1404 {0, 4, {}},
1405 // Limit 1 is only enough to reach the intermediate, no complete path
1406 // should be built.
1407 {1, 0, {target_, newintermediate_}},
1408 // Limit 2 allows reaching the root on the first path.
1409 {2, 1, {target_, newintermediate_}},
1410 // Next iteration uses oldroot instead of newroot.
1411 {3, 2, {target_, newintermediate_}},
1412 // Backtracking to the target cert.
1413 {4, 2, {target_}},
1414 // Adding oldintermediate.
1415 {5, 2, {target_, oldintermediate_}},
1416 // Trying oldroot.
1417 {6, 3, {target_, oldintermediate_}},
1418 // Trying newroot.
1419 {7, 4, {target_, oldintermediate_}},
1420 };
1421
1422 // Trust both old and new roots.
1423 TrustStoreInMemory trust_store;
1424 trust_store.AddTrustAnchor(oldroot_);
1425 trust_store.AddTrustAnchor(newroot_);
1426
1427 // Intermediates and root rollover are all provided synchronously.
1428 CertIssuerSourceStatic sync_certs;
1429 sync_certs.AddCert(oldintermediate_);
1430 sync_certs.AddCert(newintermediate_);
1431
1432 for (const auto &expectation : kExpectations) {
1433 SCOPED_TRACE(expectation.iteration_limit);
1434
1435 CertPathBuilder path_builder(
1436 target_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
1437 initial_explicit_policy_, user_initial_policy_set_,
1438 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
1439 path_builder.AddCertIssuerSource(&sync_certs);
1440
1441 // Explore all paths, rather than stopping at the first valid path.
1442 path_builder.SetExploreAllPaths(true);
1443
1444 // Limit the number of iterations.
1445 path_builder.SetIterationLimit(expectation.iteration_limit);
1446
1447 auto result = path_builder.Run();
1448
1449 EXPECT_EQ(expectation.expected_num_paths > 0, result.HasValidPath());
1450 VerifyError error = result.GetBestPathVerifyError();
1451 if (expectation.expected_num_paths > 0) {
1452 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_VERIFIED)
1453 << error.DiagnosticString();
1454 } else {
1455 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_ITERATION_COUNT_EXCEEDED)
1456 << error.DiagnosticString();
1457 }
1458
1459 if (expectation.partial_path.empty()) {
1460 ASSERT_EQ(expectation.expected_num_paths, result.paths.size());
1461 } else {
1462 ASSERT_EQ(1 + expectation.expected_num_paths, result.paths.size());
1463 const auto &path = *result.paths[result.paths.size() - 1];
1464 EXPECT_FALSE(path.IsValid());
1465 EXPECT_EQ(expectation.partial_path, path.certs);
1466 EXPECT_TRUE(
1467 path.errors.ContainsError(cert_errors::kIterationLimitExceeded));
1468 }
1469
1470 if (expectation.expected_num_paths > 0) {
1471 // Path builder will first build path: target <- newintermediate <-
1472 // newroot
1473 const auto &path0 = *result.paths[0];
1474 EXPECT_TRUE(path0.IsValid());
1475 ASSERT_EQ(3U, path0.certs.size());
1476 EXPECT_EQ(target_, path0.certs[0]);
1477 EXPECT_EQ(newintermediate_, path0.certs[1]);
1478 EXPECT_EQ(newroot_, path0.certs[2]);
1479 EXPECT_EQ(3U, result.max_depth_seen);
1480 }
1481
1482 if (expectation.expected_num_paths > 1) {
1483 // Next path: target <- newintermediate <- oldroot
1484 const auto &path1 = *result.paths[1];
1485 EXPECT_FALSE(path1.IsValid());
1486 ASSERT_EQ(3U, path1.certs.size());
1487 EXPECT_EQ(target_, path1.certs[0]);
1488 EXPECT_EQ(newintermediate_, path1.certs[1]);
1489 EXPECT_EQ(oldroot_, path1.certs[2]);
1490 EXPECT_EQ(3U, result.max_depth_seen);
1491 }
1492
1493 if (expectation.expected_num_paths > 2) {
1494 // Next path: target <- oldintermediate <- oldroot
1495 const auto &path2 = *result.paths[2];
1496 EXPECT_TRUE(path2.IsValid());
1497 ASSERT_EQ(3U, path2.certs.size());
1498 EXPECT_EQ(target_, path2.certs[0]);
1499 EXPECT_EQ(oldintermediate_, path2.certs[1]);
1500 EXPECT_EQ(oldroot_, path2.certs[2]);
1501 EXPECT_EQ(3U, result.max_depth_seen);
1502 }
1503
1504 if (expectation.expected_num_paths > 3) {
1505 // Final path: target <- oldintermediate <- newroot
1506 const auto &path3 = *result.paths[3];
1507 EXPECT_FALSE(path3.IsValid());
1508 ASSERT_EQ(3U, path3.certs.size());
1509 EXPECT_EQ(target_, path3.certs[0]);
1510 EXPECT_EQ(oldintermediate_, path3.certs[1]);
1511 EXPECT_EQ(newroot_, path3.certs[2]);
1512 EXPECT_EQ(3U, result.max_depth_seen);
1513 }
1514 }
1515 }
1516
1517 // Tests that when SetValidPathLimit is used path builder returns the number of
1518 // valid paths we expect before the valid path limit was reached.
TEST_F(PathBuilderKeyRolloverTest,ExplorePathsWithPathLimit)1519 TEST_F(PathBuilderKeyRolloverTest, ExplorePathsWithPathLimit) {
1520 struct Expectation {
1521 size_t valid_path_limit;
1522 size_t expected_num_paths;
1523 } kExpectations[] = {
1524 {0, 4}, // No path limit. Three valid, one partial path should be built
1525 {1, 1}, // One valid path
1526 {2, 3}, // Two valid, one partial
1527 {3, 4}, {4, 4}, {5, 4},
1528 };
1529
1530 // Trust both old and new roots.
1531 TrustStoreInMemory trust_store;
1532 trust_store.AddTrustAnchor(oldroot_);
1533 trust_store.AddTrustAnchor(newroot_);
1534
1535 // Intermediates and root rollover are all provided synchronously.
1536 CertIssuerSourceStatic sync_certs;
1537 sync_certs.AddCert(oldintermediate_);
1538 sync_certs.AddCert(newintermediate_);
1539
1540 for (const auto &expectation : kExpectations) {
1541 SCOPED_TRACE(expectation.valid_path_limit);
1542
1543 CertPathBuilder path_builder(
1544 target_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
1545 initial_explicit_policy_, user_initial_policy_set_,
1546 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
1547 path_builder.AddCertIssuerSource(&sync_certs);
1548
1549 // Stop after finding enough valid paths.
1550 path_builder.SetValidPathLimit(expectation.valid_path_limit);
1551
1552 auto result = path_builder.Run();
1553
1554 EXPECT_TRUE(result.HasValidPath());
1555 ASSERT_EQ(expectation.expected_num_paths, result.paths.size());
1556
1557 if (result.paths.size() > 0) {
1558 // Path builder will first build path: target <- newintermediate <-
1559 // newroot
1560 const auto &path0 = *result.paths[0];
1561 EXPECT_TRUE(path0.IsValid());
1562 ASSERT_EQ(3U, path0.certs.size());
1563 EXPECT_EQ(target_, path0.certs[0]);
1564 EXPECT_EQ(newintermediate_, path0.certs[1]);
1565 EXPECT_EQ(newroot_, path0.certs[2]);
1566 EXPECT_EQ(3U, result.max_depth_seen);
1567 }
1568
1569 if (result.paths.size() > 1) {
1570 // Next path: target <- newintermediate <- oldroot
1571 const auto &path1 = *result.paths[1];
1572 EXPECT_FALSE(path1.IsValid());
1573 ASSERT_EQ(3U, path1.certs.size());
1574 EXPECT_EQ(target_, path1.certs[0]);
1575 EXPECT_EQ(newintermediate_, path1.certs[1]);
1576 EXPECT_EQ(oldroot_, path1.certs[2]);
1577 EXPECT_EQ(3U, result.max_depth_seen);
1578 }
1579
1580 if (result.paths.size() > 2) {
1581 // Next path: target <- oldintermediate <- oldroot
1582 const auto &path2 = *result.paths[2];
1583 EXPECT_TRUE(path2.IsValid());
1584 ASSERT_EQ(3U, path2.certs.size());
1585 EXPECT_EQ(target_, path2.certs[0]);
1586 EXPECT_EQ(oldintermediate_, path2.certs[1]);
1587 EXPECT_EQ(oldroot_, path2.certs[2]);
1588 EXPECT_EQ(3U, result.max_depth_seen);
1589 }
1590
1591 if (result.paths.size() > 3) {
1592 // Final path: target <- oldintermediate <- newroot
1593 const auto &path3 = *result.paths[3];
1594 EXPECT_FALSE(path3.IsValid());
1595 ASSERT_EQ(3U, path3.certs.size());
1596 EXPECT_EQ(target_, path3.certs[0]);
1597 EXPECT_EQ(oldintermediate_, path3.certs[1]);
1598 EXPECT_EQ(newroot_, path3.certs[2]);
1599 EXPECT_EQ(3U, result.max_depth_seen);
1600 }
1601
1602 VerifyError error = result.GetBestPathVerifyError();
1603 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_VERIFIED)
1604 << error.DiagnosticString();
1605 }
1606 }
1607
1608 // If the target cert is a trust anchor, however is not itself *signed* by a
1609 // trust anchor, then it is not considered valid (the SPKI and name of the
1610 // trust anchor matches the SPKI and subject of the target certificate, but the
1611 // rest of the certificate cannot be verified).
TEST_F(PathBuilderKeyRolloverTest,TestEndEntityIsTrustRoot)1612 TEST_F(PathBuilderKeyRolloverTest, TestEndEntityIsTrustRoot) {
1613 // Trust newintermediate.
1614 TrustStoreInMemory trust_store;
1615 trust_store.AddTrustAnchor(newintermediate_);
1616
1617 // Newintermediate is also the target cert.
1618 CertPathBuilder path_builder(
1619 newintermediate_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
1620 initial_explicit_policy_, user_initial_policy_set_,
1621 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
1622
1623 auto result = path_builder.Run();
1624
1625 EXPECT_FALSE(result.HasValidPath());
1626
1627 VerifyError error = result.GetBestPathVerifyError();
1628 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_NOT_FOUND)
1629 << error.DiagnosticString();
1630 }
1631
1632 // If target has same Name+SAN+SPKI as a necessary intermediate, test if a path
1633 // can still be built.
1634 // Since LoopChecker will prevent the intermediate from being included, this
1635 // currently does NOT verify. This case shouldn't occur in the web PKI.
TEST_F(PathBuilderKeyRolloverTest,TestEndEntityHasSameNameAndSpkiAsIntermediate)1636 TEST_F(PathBuilderKeyRolloverTest,
1637 TestEndEntityHasSameNameAndSpkiAsIntermediate) {
1638 // Trust oldroot.
1639 TrustStoreInMemory trust_store;
1640 trust_store.AddTrustAnchor(oldroot_);
1641
1642 // New root rollover is provided synchronously.
1643 CertIssuerSourceStatic sync_certs;
1644 sync_certs.AddCert(newrootrollover_);
1645
1646 // Newroot is the target cert.
1647 CertPathBuilder path_builder(
1648 newroot_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
1649 initial_explicit_policy_, user_initial_policy_set_,
1650 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
1651 path_builder.AddCertIssuerSource(&sync_certs);
1652
1653 auto result = path_builder.Run();
1654
1655 // This could actually be OK, but CertPathBuilder does not build the
1656 // newroot <- newrootrollover <- oldroot path.
1657 EXPECT_FALSE(result.HasValidPath());
1658
1659 VerifyError error = result.GetBestPathVerifyError();
1660 ASSERT_EQ(error.Code(),
1661 VerifyError::StatusCode::CERTIFICATE_INVALID_SIGNATURE)
1662 << error.DiagnosticString();
1663 }
1664
1665 // If target has same Name+SAN+SPKI as the trust root, test that a (trivial)
1666 // path can still be built.
TEST_F(PathBuilderKeyRolloverTest,TestEndEntityHasSameNameAndSpkiAsTrustAnchor)1667 TEST_F(PathBuilderKeyRolloverTest,
1668 TestEndEntityHasSameNameAndSpkiAsTrustAnchor) {
1669 // Trust newrootrollover.
1670 TrustStoreInMemory trust_store;
1671 trust_store.AddTrustAnchor(newrootrollover_);
1672
1673 // Newroot is the target cert.
1674 CertPathBuilder path_builder(
1675 newroot_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
1676 initial_explicit_policy_, user_initial_policy_set_,
1677 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
1678
1679 auto result = path_builder.Run();
1680
1681 ASSERT_TRUE(result.HasValidPath());
1682
1683 const CertPathBuilderResultPath *best_result = result.GetBestValidPath();
1684
1685 // Newroot has same name+SPKI as newrootrollover, thus the path is valid and
1686 // only contains newroot.
1687 EXPECT_TRUE(best_result->IsValid());
1688 ASSERT_EQ(2U, best_result->certs.size());
1689 EXPECT_EQ(newroot_, best_result->certs[0]);
1690 EXPECT_EQ(newrootrollover_, best_result->certs[1]);
1691
1692 VerifyError error = result.GetBestPathVerifyError();
1693 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_VERIFIED)
1694 << error.DiagnosticString();
1695 }
1696
1697 // Test that PathBuilder will not try the same path twice if multiple
1698 // CertIssuerSources provide the same certificate.
TEST_F(PathBuilderKeyRolloverTest,TestDuplicateIntermediates)1699 TEST_F(PathBuilderKeyRolloverTest, TestDuplicateIntermediates) {
1700 // Create a separate copy of oldintermediate.
1701 std::shared_ptr<const ParsedCertificate> oldintermediate_dupe(
1702 ParsedCertificate::Create(
1703 bssl::UniquePtr<CRYPTO_BUFFER>(
1704 CRYPTO_BUFFER_new(oldintermediate_->der_cert().data(),
1705 oldintermediate_->der_cert().size(), nullptr)),
1706 {}, nullptr));
1707
1708 // Only newroot is a trusted root.
1709 TrustStoreInMemory trust_store;
1710 trust_store.AddTrustAnchor(newroot_);
1711
1712 // The oldintermediate is supplied synchronously by |sync_certs1| and
1713 // another copy of oldintermediate is supplied synchronously by |sync_certs2|.
1714 // The path target <- oldintermediate <- newroot should be built first,
1715 // though it won't verify. It should not be attempted again even though
1716 // oldintermediate was supplied twice.
1717 CertIssuerSourceStatic sync_certs1;
1718 sync_certs1.AddCert(oldintermediate_);
1719 CertIssuerSourceStatic sync_certs2;
1720 sync_certs2.AddCert(oldintermediate_dupe);
1721
1722 // The newintermediate is supplied asynchronously, so the path
1723 // target <- newintermediate <- newroot should be tried second.
1724 AsyncCertIssuerSourceStatic async_certs;
1725 async_certs.AddCert(newintermediate_);
1726
1727 CertPathBuilder path_builder(
1728 target_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
1729 initial_explicit_policy_, user_initial_policy_set_,
1730 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
1731 path_builder.AddCertIssuerSource(&sync_certs1);
1732 path_builder.AddCertIssuerSource(&sync_certs2);
1733 path_builder.AddCertIssuerSource(&async_certs);
1734
1735 auto result = path_builder.Run();
1736
1737 EXPECT_TRUE(result.HasValidPath());
1738 ASSERT_EQ(2U, result.paths.size());
1739
1740 // Path builder will first attempt: target <- oldintermediate <- newroot
1741 // but it will fail since oldintermediate is signed by oldroot.
1742 EXPECT_FALSE(result.paths[0]->IsValid());
1743 const auto &path0 = *result.paths[0];
1744
1745 ASSERT_EQ(3U, path0.certs.size());
1746 EXPECT_EQ(target_, path0.certs[0]);
1747 // Compare the DER instead of ParsedCertificate pointer, don't care which copy
1748 // of oldintermediate was used in the path.
1749 EXPECT_EQ(oldintermediate_->der_cert(), path0.certs[1]->der_cert());
1750 EXPECT_EQ(newroot_, path0.certs[2]);
1751
1752 // Path builder will next attempt: target <- newintermediate <- newroot
1753 // which will succeed.
1754 EXPECT_EQ(1U, result.best_result_index);
1755 EXPECT_TRUE(result.paths[1]->IsValid());
1756 const auto &path1 = *result.paths[1];
1757 ASSERT_EQ(3U, path1.certs.size());
1758 EXPECT_EQ(target_, path1.certs[0]);
1759 EXPECT_EQ(newintermediate_, path1.certs[1]);
1760 EXPECT_EQ(newroot_, path1.certs[2]);
1761
1762 VerifyError error = result.GetBestPathVerifyError();
1763 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_VERIFIED)
1764 << error.DiagnosticString();
1765 }
1766
1767 // Test when PathBuilder is given a cert via CertIssuerSources that has the same
1768 // SPKI as a trust anchor.
TEST_F(PathBuilderKeyRolloverTest,TestDuplicateIntermediateAndRoot)1769 TEST_F(PathBuilderKeyRolloverTest, TestDuplicateIntermediateAndRoot) {
1770 // Create a separate copy of newroot.
1771 std::shared_ptr<const ParsedCertificate> newroot_dupe(
1772 ParsedCertificate::Create(
1773 bssl::UniquePtr<CRYPTO_BUFFER>(
1774 CRYPTO_BUFFER_new(newroot_->der_cert().data(),
1775 newroot_->der_cert().size(), nullptr)),
1776 {}, nullptr));
1777
1778 // Only newroot is a trusted root.
1779 TrustStoreInMemory trust_store;
1780 trust_store.AddTrustAnchor(newroot_);
1781
1782 // The oldintermediate and newroot are supplied synchronously by |sync_certs|.
1783 CertIssuerSourceStatic sync_certs;
1784 sync_certs.AddCert(oldintermediate_);
1785 sync_certs.AddCert(newroot_dupe);
1786
1787 CertPathBuilder path_builder(
1788 target_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
1789 initial_explicit_policy_, user_initial_policy_set_,
1790 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
1791 path_builder.AddCertIssuerSource(&sync_certs);
1792
1793 auto result = path_builder.Run();
1794
1795 EXPECT_FALSE(result.HasValidPath());
1796 ASSERT_EQ(1U, result.paths.size());
1797
1798 // Path builder attempt: target <- oldintermediate <- newroot
1799 // but it will fail since oldintermediate is signed by oldroot.
1800 EXPECT_FALSE(result.paths[0]->IsValid());
1801 const auto &path = *result.paths[0];
1802 ASSERT_EQ(3U, path.certs.size());
1803 EXPECT_EQ(target_, path.certs[0]);
1804 EXPECT_EQ(oldintermediate_, path.certs[1]);
1805 // Compare the DER instead of ParsedCertificate pointer, don't care which copy
1806 // of newroot was used in the path.
1807 EXPECT_EQ(newroot_->der_cert(), path.certs[2]->der_cert());
1808
1809 VerifyError error = result.GetBestPathVerifyError();
1810 ASSERT_EQ(error.Code(),
1811 VerifyError::StatusCode::CERTIFICATE_INVALID_SIGNATURE)
1812 << error.DiagnosticString();
1813 }
1814
1815 class MockCertIssuerSourceRequest : public CertIssuerSource::Request {
1816 public:
1817 MOCK_METHOD1(GetNext, void(ParsedCertificateList *));
1818 };
1819
1820 class MockCertIssuerSource : public CertIssuerSource {
1821 public:
1822 MOCK_METHOD2(SyncGetIssuersOf,
1823 void(const ParsedCertificate *, ParsedCertificateList *));
1824 MOCK_METHOD2(AsyncGetIssuersOf,
1825 void(const ParsedCertificate *, std::unique_ptr<Request> *));
1826 };
1827
1828 // Helper class to pass the Request to the PathBuilder when it calls
1829 // AsyncGetIssuersOf. (GoogleMock has a ByMove helper, but it apparently can
1830 // only be used with Return, not SetArgPointee.)
1831 class CertIssuerSourceRequestMover {
1832 public:
CertIssuerSourceRequestMover(std::unique_ptr<CertIssuerSource::Request> req)1833 explicit CertIssuerSourceRequestMover(
1834 std::unique_ptr<CertIssuerSource::Request> req)
1835 : request_(std::move(req)) {}
MoveIt(const ParsedCertificate * cert,std::unique_ptr<CertIssuerSource::Request> * out_req)1836 void MoveIt(const ParsedCertificate *cert,
1837 std::unique_ptr<CertIssuerSource::Request> *out_req) {
1838 *out_req = std::move(request_);
1839 }
1840
1841 private:
1842 std::unique_ptr<CertIssuerSource::Request> request_;
1843 };
1844
1845 // Functor that when called with a ParsedCertificateList* will append the
1846 // specified certificate.
1847 class AppendCertToList {
1848 public:
AppendCertToList(const std::shared_ptr<const ParsedCertificate> & cert)1849 explicit AppendCertToList(
1850 const std::shared_ptr<const ParsedCertificate> &cert)
1851 : cert_(cert) {}
1852
operator ()(ParsedCertificateList * out)1853 void operator()(ParsedCertificateList *out) { out->push_back(cert_); }
1854
1855 private:
1856 std::shared_ptr<const ParsedCertificate> cert_;
1857 };
1858
1859 // Test that a single CertIssuerSource returning multiple async batches of
1860 // issuers is handled correctly. Due to the StrictMocks, it also tests that path
1861 // builder does not request issuers of certs that it shouldn't.
TEST_F(PathBuilderKeyRolloverTest,TestMultipleAsyncIssuersFromSingleSource)1862 TEST_F(PathBuilderKeyRolloverTest, TestMultipleAsyncIssuersFromSingleSource) {
1863 StrictMock<MockCertIssuerSource> cert_issuer_source;
1864
1865 // Only newroot is a trusted root.
1866 TrustStoreInMemory trust_store;
1867 trust_store.AddTrustAnchor(newroot_);
1868
1869 CertPathBuilder path_builder(
1870 target_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
1871 initial_explicit_policy_, user_initial_policy_set_,
1872 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
1873 path_builder.AddCertIssuerSource(&cert_issuer_source);
1874
1875 // Create the mock CertIssuerSource::Request...
1876 auto target_issuers_req_owner =
1877 std::make_unique<StrictMock<MockCertIssuerSourceRequest>>();
1878 // Keep a raw pointer to the Request...
1879 StrictMock<MockCertIssuerSourceRequest> *target_issuers_req =
1880 target_issuers_req_owner.get();
1881 // Setup helper class to pass ownership of the Request to the PathBuilder when
1882 // it calls AsyncGetIssuersOf.
1883 CertIssuerSourceRequestMover req_mover(std::move(target_issuers_req_owner));
1884 {
1885 ::testing::InSequence s;
1886 EXPECT_CALL(cert_issuer_source, SyncGetIssuersOf(target_.get(), _));
1887 EXPECT_CALL(cert_issuer_source, AsyncGetIssuersOf(target_.get(), _))
1888 .WillOnce(Invoke(&req_mover, &CertIssuerSourceRequestMover::MoveIt));
1889 }
1890
1891 EXPECT_CALL(*target_issuers_req, GetNext(_))
1892 // First async batch: return oldintermediate_.
1893 .WillOnce(Invoke(AppendCertToList(oldintermediate_)))
1894 // Second async batch: return newintermediate_.
1895 .WillOnce(Invoke(AppendCertToList(newintermediate_)));
1896 {
1897 ::testing::InSequence s;
1898 // oldintermediate_ does not create a valid path, so both sync and async
1899 // lookups are expected.
1900 EXPECT_CALL(cert_issuer_source,
1901 SyncGetIssuersOf(oldintermediate_.get(), _));
1902 EXPECT_CALL(cert_issuer_source,
1903 AsyncGetIssuersOf(oldintermediate_.get(), _));
1904 }
1905
1906 // newroot_ is in the trust store, so this path will be completed
1907 // synchronously. AsyncGetIssuersOf will not be called on newintermediate_.
1908 EXPECT_CALL(cert_issuer_source, SyncGetIssuersOf(newintermediate_.get(), _));
1909
1910 // Ensure pathbuilder finished and filled result.
1911 auto result = path_builder.Run();
1912
1913 // Note that VerifyAndClearExpectations(target_issuers_req) is not called
1914 // here. PathBuilder could have destroyed it already, so just let the
1915 // expectations get checked by the destructor.
1916 ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
1917
1918 EXPECT_TRUE(result.HasValidPath());
1919 ASSERT_EQ(2U, result.paths.size());
1920
1921 // Path builder first attempts: target <- oldintermediate <- newroot
1922 // but it will fail since oldintermediate is signed by oldroot.
1923 EXPECT_FALSE(result.paths[0]->IsValid());
1924 const auto &path0 = *result.paths[0];
1925 ASSERT_EQ(3U, path0.certs.size());
1926 EXPECT_EQ(target_, path0.certs[0]);
1927 EXPECT_EQ(oldintermediate_, path0.certs[1]);
1928 EXPECT_EQ(newroot_, path0.certs[2]);
1929
1930 // After the second batch of async results, path builder will attempt:
1931 // target <- newintermediate <- newroot which will succeed.
1932 EXPECT_TRUE(result.paths[1]->IsValid());
1933 const auto &path1 = *result.paths[1];
1934 ASSERT_EQ(3U, path1.certs.size());
1935 EXPECT_EQ(target_, path1.certs[0]);
1936 EXPECT_EQ(newintermediate_, path1.certs[1]);
1937 EXPECT_EQ(newroot_, path1.certs[2]);
1938
1939 VerifyError error = result.GetBestPathVerifyError();
1940 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_VERIFIED)
1941 << error.DiagnosticString();
1942 }
1943
1944 // Test that PathBuilder will not try the same path twice if CertIssuerSources
1945 // asynchronously provide the same certificate multiple times.
TEST_F(PathBuilderKeyRolloverTest,TestDuplicateAsyncIntermediates)1946 TEST_F(PathBuilderKeyRolloverTest, TestDuplicateAsyncIntermediates) {
1947 StrictMock<MockCertIssuerSource> cert_issuer_source;
1948
1949 // Only newroot is a trusted root.
1950 TrustStoreInMemory trust_store;
1951 trust_store.AddTrustAnchor(newroot_);
1952
1953 CertPathBuilder path_builder(
1954 target_, &trust_store, &delegate_, time_, KeyPurpose::ANY_EKU,
1955 initial_explicit_policy_, user_initial_policy_set_,
1956 initial_policy_mapping_inhibit_, initial_any_policy_inhibit_);
1957 path_builder.AddCertIssuerSource(&cert_issuer_source);
1958
1959 // Create the mock CertIssuerSource::Request...
1960 auto target_issuers_req_owner =
1961 std::make_unique<StrictMock<MockCertIssuerSourceRequest>>();
1962 // Keep a raw pointer to the Request...
1963 StrictMock<MockCertIssuerSourceRequest> *target_issuers_req =
1964 target_issuers_req_owner.get();
1965 // Setup helper class to pass ownership of the Request to the PathBuilder when
1966 // it calls AsyncGetIssuersOf.
1967 CertIssuerSourceRequestMover req_mover(std::move(target_issuers_req_owner));
1968 {
1969 ::testing::InSequence s;
1970 EXPECT_CALL(cert_issuer_source, SyncGetIssuersOf(target_.get(), _));
1971 EXPECT_CALL(cert_issuer_source, AsyncGetIssuersOf(target_.get(), _))
1972 .WillOnce(Invoke(&req_mover, &CertIssuerSourceRequestMover::MoveIt));
1973 }
1974
1975 std::shared_ptr<const ParsedCertificate> oldintermediate_dupe(
1976 ParsedCertificate::Create(
1977 bssl::UniquePtr<CRYPTO_BUFFER>(
1978 CRYPTO_BUFFER_new(oldintermediate_->der_cert().data(),
1979 oldintermediate_->der_cert().size(), nullptr)),
1980 {}, nullptr));
1981
1982 EXPECT_CALL(*target_issuers_req, GetNext(_))
1983 // First async batch: return oldintermediate_.
1984 .WillOnce(Invoke(AppendCertToList(oldintermediate_)))
1985 // Second async batch: return a different copy of oldintermediate_ again.
1986 .WillOnce(Invoke(AppendCertToList(oldintermediate_dupe)))
1987 // Third async batch: return newintermediate_.
1988 .WillOnce(Invoke(AppendCertToList(newintermediate_)));
1989
1990 {
1991 ::testing::InSequence s;
1992 // oldintermediate_ does not create a valid path, so both sync and async
1993 // lookups are expected.
1994 EXPECT_CALL(cert_issuer_source,
1995 SyncGetIssuersOf(oldintermediate_.get(), _));
1996 EXPECT_CALL(cert_issuer_source,
1997 AsyncGetIssuersOf(oldintermediate_.get(), _));
1998 }
1999
2000 // newroot_ is in the trust store, so this path will be completed
2001 // synchronously. AsyncGetIssuersOf will not be called on newintermediate_.
2002 EXPECT_CALL(cert_issuer_source, SyncGetIssuersOf(newintermediate_.get(), _));
2003
2004 // Ensure pathbuilder finished and filled result.
2005 auto result = path_builder.Run();
2006
2007 ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
2008
2009 EXPECT_TRUE(result.HasValidPath());
2010 ASSERT_EQ(2U, result.paths.size());
2011
2012 // Path builder first attempts: target <- oldintermediate <- newroot
2013 // but it will fail since oldintermediate is signed by oldroot.
2014 EXPECT_FALSE(result.paths[0]->IsValid());
2015 const auto &path0 = *result.paths[0];
2016 ASSERT_EQ(3U, path0.certs.size());
2017 EXPECT_EQ(target_, path0.certs[0]);
2018 EXPECT_EQ(oldintermediate_, path0.certs[1]);
2019 EXPECT_EQ(newroot_, path0.certs[2]);
2020
2021 // The second async result does not generate any path.
2022
2023 // After the third batch of async results, path builder will attempt:
2024 // target <- newintermediate <- newroot which will succeed.
2025 EXPECT_TRUE(result.paths[1]->IsValid());
2026 const auto &path1 = *result.paths[1];
2027 ASSERT_EQ(3U, path1.certs.size());
2028 EXPECT_EQ(target_, path1.certs[0]);
2029 EXPECT_EQ(newintermediate_, path1.certs[1]);
2030 EXPECT_EQ(newroot_, path1.certs[2]);
2031
2032 VerifyError error = result.GetBestPathVerifyError();
2033 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_VERIFIED)
2034 << error.DiagnosticString();
2035 }
2036
2037 class PathBuilderSimpleChainTest : public ::testing::Test {
2038 public:
2039 PathBuilderSimpleChainTest() = default;
2040
2041 protected:
SetUp()2042 void SetUp() override {
2043 // Read a simple test chain comprised of a target, intermediate, and root.
2044 ASSERT_TRUE(ReadVerifyCertChainTestFromFile(
2045 "testdata/verify_certificate_chain_unittest/target-and-intermediate/"
2046 "main.test",
2047 &test_));
2048 ASSERT_EQ(3u, test_.chain.size());
2049 }
2050
2051 // Runs the path builder for the target certificate while |distrusted_cert| is
2052 // blocked, and |delegate| if non-null.
RunPathBuilder(const std::shared_ptr<const ParsedCertificate> & distrusted_cert,CertPathBuilderDelegate * optional_delegate)2053 CertPathBuilder::Result RunPathBuilder(
2054 const std::shared_ptr<const ParsedCertificate> &distrusted_cert,
2055 CertPathBuilderDelegate *optional_delegate) {
2056 // Set up the trust store such that |distrusted_cert| is blocked, and
2057 // the root is trusted (except if it was |distrusted_cert|).
2058 TrustStoreInMemory trust_store;
2059 if (distrusted_cert != test_.chain.back()) {
2060 trust_store.AddTrustAnchor(test_.chain.back());
2061 }
2062 if (distrusted_cert) {
2063 trust_store.AddDistrustedCertificateForTest(distrusted_cert);
2064 }
2065
2066 // Add the single intermediate.
2067 CertIssuerSourceStatic intermediates;
2068 intermediates.AddCert(test_.chain[1]);
2069
2070 SimplePathBuilderDelegate default_delegate(
2071 1024, SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1);
2072 CertPathBuilderDelegate *delegate =
2073 optional_delegate ? optional_delegate : &default_delegate;
2074
2075 const InitialExplicitPolicy initial_explicit_policy =
2076 InitialExplicitPolicy::kFalse;
2077 const std::set<der::Input> user_initial_policy_set = {
2078 der::Input(kAnyPolicyOid)};
2079 const InitialPolicyMappingInhibit initial_policy_mapping_inhibit =
2080 InitialPolicyMappingInhibit::kFalse;
2081 const InitialAnyPolicyInhibit initial_any_policy_inhibit =
2082 InitialAnyPolicyInhibit::kFalse;
2083
2084 CertPathBuilder path_builder(
2085 test_.chain.front(), &trust_store, delegate, test_.time,
2086 KeyPurpose::ANY_EKU, initial_explicit_policy, user_initial_policy_set,
2087 initial_policy_mapping_inhibit, initial_any_policy_inhibit);
2088 path_builder.AddCertIssuerSource(&intermediates);
2089 return path_builder.Run();
2090 }
2091
2092 protected:
2093 VerifyCertChainTest test_;
2094 };
2095
2096 // Test fixture for running the path builder over a simple chain, while varying
2097 // the trustedness of certain certificates.
2098 class PathBuilderDistrustTest : public PathBuilderSimpleChainTest {
2099 public:
2100 PathBuilderDistrustTest() = default;
2101
2102 protected:
2103 // Runs the path builder for the target certificate while |distrusted_cert| is
2104 // blocked.
RunPathBuilderWithDistrustedCert(const std::shared_ptr<const ParsedCertificate> & distrusted_cert)2105 CertPathBuilder::Result RunPathBuilderWithDistrustedCert(
2106 const std::shared_ptr<const ParsedCertificate> &distrusted_cert) {
2107 return RunPathBuilder(distrusted_cert, nullptr);
2108 }
2109 };
2110
2111 // Tests that path building fails when the target, intermediate, or root are
2112 // distrusted (but the path is otherwise valid).
TEST_F(PathBuilderDistrustTest,TargetIntermediateRoot)2113 TEST_F(PathBuilderDistrustTest, TargetIntermediateRoot) {
2114 // First do a control test -- path building without any blocked
2115 // certificates should work.
2116 CertPathBuilder::Result result = RunPathBuilderWithDistrustedCert(nullptr);
2117 {
2118 ASSERT_TRUE(result.HasValidPath());
2119 // The built path should be identical the the one read from disk.
2120 const auto &path = *result.GetBestValidPath();
2121 ASSERT_EQ(test_.chain.size(), path.certs.size());
2122 for (size_t i = 0; i < test_.chain.size(); ++i) {
2123 EXPECT_EQ(test_.chain[i], path.certs[i]);
2124 }
2125 }
2126
2127 // Try path building when only the target is blocked - should fail.
2128 result = RunPathBuilderWithDistrustedCert(test_.chain[0]);
2129 {
2130 EXPECT_FALSE(result.HasValidPath());
2131 ASSERT_LT(result.best_result_index, result.paths.size());
2132 const auto &best_path = result.paths[result.best_result_index];
2133
2134 // The built chain has length 1 since path building stopped once
2135 // it encountered the blocked certificate (target).
2136 ASSERT_EQ(1u, best_path->certs.size());
2137 EXPECT_EQ(best_path->certs[0], test_.chain[0]);
2138 EXPECT_TRUE(best_path->errors.ContainsHighSeverityErrors());
2139 best_path->errors.ContainsError(cert_errors::kDistrustedByTrustStore);
2140 }
2141
2142 // Try path building when only the intermediate is blocked - should fail.
2143 result = RunPathBuilderWithDistrustedCert(test_.chain[1]);
2144 {
2145 EXPECT_FALSE(result.HasValidPath());
2146 ASSERT_LT(result.best_result_index, result.paths.size());
2147 const auto &best_path = result.paths[result.best_result_index];
2148
2149 // The built chain has length 2 since path building stopped once
2150 // it encountered the blocked certificate (intermediate).
2151 ASSERT_EQ(2u, best_path->certs.size());
2152 EXPECT_EQ(best_path->certs[0], test_.chain[0]);
2153 EXPECT_EQ(best_path->certs[1], test_.chain[1]);
2154 EXPECT_TRUE(best_path->errors.ContainsHighSeverityErrors());
2155 best_path->errors.ContainsError(cert_errors::kDistrustedByTrustStore);
2156 }
2157
2158 // Try path building when only the root is blocked - should fail.
2159 result = RunPathBuilderWithDistrustedCert(test_.chain[2]);
2160 {
2161 EXPECT_FALSE(result.HasValidPath());
2162 ASSERT_LT(result.best_result_index, result.paths.size());
2163 const auto &best_path = result.paths[result.best_result_index];
2164
2165 // The built chain has length 3 since path building stopped once
2166 // it encountered the blocked certificate (root).
2167 ASSERT_EQ(3u, best_path->certs.size());
2168 EXPECT_EQ(best_path->certs[0], test_.chain[0]);
2169 EXPECT_EQ(best_path->certs[1], test_.chain[1]);
2170 EXPECT_EQ(best_path->certs[2], test_.chain[2]);
2171 EXPECT_TRUE(best_path->errors.ContainsHighSeverityErrors());
2172 best_path->errors.ContainsError(cert_errors::kDistrustedByTrustStore);
2173 }
2174 }
2175
2176 // Test fixture for running the path builder over a simple chain, while varying
2177 // what CheckPathAfterVerification() does.
2178 class PathBuilderCheckPathAfterVerificationTest
2179 : public PathBuilderSimpleChainTest {};
2180
TEST_F(PathBuilderCheckPathAfterVerificationTest,NoOpToValidPath)2181 TEST_F(PathBuilderCheckPathAfterVerificationTest, NoOpToValidPath) {
2182 StrictMock<MockPathBuilderDelegate> delegate;
2183 // Just verify that the hook is called.
2184 EXPECT_CALL(delegate, CheckPathAfterVerification(_, _));
2185
2186 CertPathBuilder::Result result = RunPathBuilder(nullptr, &delegate);
2187 EXPECT_TRUE(result.HasValidPath());
2188 }
2189
2190 DEFINE_CERT_ERROR_ID(kWarningFromDelegate, "Warning from delegate");
2191
2192 class AddWarningPathBuilderDelegate : public CertPathBuilderDelegateBase {
2193 public:
CheckPathAfterVerification(const CertPathBuilder & path_builder,CertPathBuilderResultPath * path)2194 void CheckPathAfterVerification(const CertPathBuilder &path_builder,
2195 CertPathBuilderResultPath *path) override {
2196 path->errors.GetErrorsForCert(1)->AddWarning(kWarningFromDelegate, nullptr);
2197 }
2198 };
2199
TEST_F(PathBuilderCheckPathAfterVerificationTest,AddsWarningToValidPath)2200 TEST_F(PathBuilderCheckPathAfterVerificationTest, AddsWarningToValidPath) {
2201 AddWarningPathBuilderDelegate delegate;
2202 CertPathBuilder::Result result = RunPathBuilder(nullptr, &delegate);
2203 ASSERT_TRUE(result.HasValidPath());
2204
2205 // A warning should have been added to certificate at index 1 in the path.
2206 const CertErrors *cert1_errors =
2207 result.GetBestValidPath()->errors.GetErrorsForCert(1);
2208 ASSERT_TRUE(cert1_errors);
2209 EXPECT_TRUE(cert1_errors->ContainsErrorWithSeverity(
2210 kWarningFromDelegate, CertError::SEVERITY_WARNING));
2211
2212 // The warning should not affect the VerifyError
2213 VerifyError error = result.GetBestPathVerifyError();
2214 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_VERIFIED)
2215 << error.DiagnosticString();
2216 }
2217
TEST_F(PathBuilderCheckPathAfterVerificationTest,TestVerifyErrorMapping)2218 TEST_F(PathBuilderCheckPathAfterVerificationTest, TestVerifyErrorMapping) {
2219 struct error_mapping {
2220 CertErrorId internal_error;
2221 VerifyError::StatusCode code;
2222 };
2223 struct error_mapping AllErrors[] = {
2224 {cert_errors::kInternalError,
2225 VerifyError::StatusCode::VERIFICATION_FAILURE},
2226 {cert_errors::kValidityFailedNotAfter,
2227 VerifyError::StatusCode::CERTIFICATE_EXPIRED},
2228 {cert_errors::kValidityFailedNotBefore,
2229 VerifyError::StatusCode::CERTIFICATE_NOT_YET_VALID},
2230 {cert_errors::kDistrustedByTrustStore,
2231 VerifyError::StatusCode::PATH_NOT_FOUND},
2232 {cert_errors::kSignatureAlgorithmMismatch,
2233 VerifyError::StatusCode::CERTIFICATE_INVALID},
2234 {cert_errors::kChainIsEmpty,
2235 VerifyError::StatusCode::VERIFICATION_FAILURE},
2236 {cert_errors::kUnconsumedCriticalExtension,
2237 VerifyError::StatusCode::CERTIFICATE_INVALID},
2238 {cert_errors::kKeyCertSignBitNotSet,
2239 VerifyError::StatusCode::CERTIFICATE_INVALID},
2240 {cert_errors::kMaxPathLengthViolated,
2241 VerifyError::StatusCode::PATH_NOT_FOUND},
2242 {cert_errors::kBasicConstraintsIndicatesNotCa,
2243 VerifyError::StatusCode::CERTIFICATE_INVALID},
2244 {cert_errors::kTargetCertShouldNotBeCa,
2245 VerifyError::StatusCode::CERTIFICATE_INVALID},
2246 {cert_errors::kMissingBasicConstraints,
2247 VerifyError::StatusCode::CERTIFICATE_INVALID},
2248 {cert_errors::kNotPermittedByNameConstraints,
2249 VerifyError::StatusCode::CERTIFICATE_INVALID},
2250 {cert_errors::kTooManyNameConstraintChecks,
2251 VerifyError::StatusCode::CERTIFICATE_INVALID},
2252 {cert_errors::kSubjectDoesNotMatchIssuer,
2253 VerifyError::StatusCode::PATH_NOT_FOUND},
2254 {cert_errors::kVerifySignedDataFailed,
2255 VerifyError::StatusCode::CERTIFICATE_INVALID_SIGNATURE},
2256 {cert_errors::kSignatureAlgorithmsDifferentEncoding,
2257 VerifyError::StatusCode::CERTIFICATE_INVALID},
2258 {cert_errors::kEkuLacksServerAuth,
2259 VerifyError::StatusCode::CERTIFICATE_NO_MATCHING_EKU},
2260 {cert_errors::kEkuLacksServerAuthButHasAnyEKU,
2261 VerifyError::StatusCode::CERTIFICATE_NO_MATCHING_EKU},
2262 {cert_errors::kEkuLacksClientAuth,
2263 VerifyError::StatusCode::CERTIFICATE_NO_MATCHING_EKU},
2264 {cert_errors::kEkuLacksClientAuthButHasAnyEKU,
2265 VerifyError::StatusCode::CERTIFICATE_NO_MATCHING_EKU},
2266 {cert_errors::kEkuLacksClientAuthOrServerAuth,
2267 VerifyError::StatusCode::CERTIFICATE_NO_MATCHING_EKU},
2268 {cert_errors::kEkuHasProhibitedOCSPSigning,
2269 VerifyError::StatusCode::CERTIFICATE_INVALID},
2270 {cert_errors::kEkuHasProhibitedTimeStamping,
2271 VerifyError::StatusCode::CERTIFICATE_INVALID},
2272 {cert_errors::kEkuHasProhibitedCodeSigning,
2273 VerifyError::StatusCode::CERTIFICATE_INVALID},
2274 {cert_errors::kEkuNotPresent,
2275 VerifyError::StatusCode::CERTIFICATE_INVALID},
2276 {cert_errors::kCertIsNotTrustAnchor,
2277 VerifyError::StatusCode::PATH_NOT_FOUND},
2278 {cert_errors::kNoValidPolicy,
2279 VerifyError::StatusCode::CERTIFICATE_INVALID},
2280 {cert_errors::kPolicyMappingAnyPolicy,
2281 VerifyError::StatusCode::CERTIFICATE_INVALID},
2282 {cert_errors::kFailedParsingSpki,
2283 VerifyError::StatusCode::CERTIFICATE_INVALID},
2284 {cert_errors::kUnacceptableSignatureAlgorithm,
2285 VerifyError::StatusCode::CERTIFICATE_UNSUPPORTED_SIGNATURE_ALGORITHM},
2286 {cert_errors::kUnacceptablePublicKey,
2287 VerifyError::StatusCode::CERTIFICATE_UNSUPPORTED_KEY},
2288 {cert_errors::kCertificateRevoked,
2289 VerifyError::StatusCode::CERTIFICATE_REVOKED},
2290 {cert_errors::kNoRevocationMechanism,
2291 VerifyError::StatusCode::CERTIFICATE_NO_REVOCATION_MECHANISM},
2292 {cert_errors::kUnableToCheckRevocation,
2293 VerifyError::StatusCode::CERTIFICATE_UNABLE_TO_CHECK_REVOCATION},
2294 {cert_errors::kNoIssuersFound, VerifyError::StatusCode::PATH_NOT_FOUND},
2295 {cert_errors::kDeadlineExceeded,
2296 VerifyError::StatusCode::PATH_DEADLINE_EXCEEDED},
2297 {cert_errors::kIterationLimitExceeded,
2298 VerifyError::StatusCode::PATH_ITERATION_COUNT_EXCEEDED},
2299 {cert_errors::kDepthLimitExceeded,
2300 VerifyError::StatusCode::PATH_DEPTH_LIMIT_REACHED},
2301 };
2302
2303 for (struct error_mapping mapping : AllErrors) {
2304 AddWarningPathBuilderDelegate delegate;
2305 CertPathBuilder::Result result = RunPathBuilder(nullptr, &delegate);
2306 ASSERT_TRUE(result.HasValidPath());
2307
2308 CertErrors *errors =
2309 (CertErrors *)result.GetBestValidPath()->errors.GetErrorsForCert(1);
2310 errors->AddError(mapping.internal_error, nullptr);
2311
2312 VerifyError error = result.GetBestPathVerifyError();
2313 ASSERT_EQ(error.Code(), mapping.code)
2314 << error.DiagnosticString();
2315 }
2316 }
2317
TEST_F(PathBuilderCheckPathAfterVerificationTest,TestVerifyErrorMulipleMapping)2318 TEST_F(PathBuilderCheckPathAfterVerificationTest,
2319 TestVerifyErrorMulipleMapping) {
2320 AddWarningPathBuilderDelegate delegate;
2321 CertPathBuilder::Result result = RunPathBuilder(nullptr, &delegate);
2322 ASSERT_TRUE(result.HasValidPath());
2323
2324 CertErrors *errors =
2325 (CertErrors *)result.GetBestValidPath()->errors.GetErrorsForCert(1);
2326 errors->AddError(cert_errors::kEkuNotPresent, nullptr);
2327 errors->AddError(cert_errors::kNoValidPolicy, nullptr);
2328
2329 VerifyError error = result.GetBestPathVerifyError();
2330 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_MULTIPLE_ERRORS)
2331 << error.DiagnosticString();
2332 }
2333
2334
2335 DEFINE_CERT_ERROR_ID(kErrorFromDelegate, "Error from delegate");
2336
2337 class AddErrorPathBuilderDelegate : public CertPathBuilderDelegateBase {
2338 public:
CheckPathAfterVerification(const CertPathBuilder & path_builder,CertPathBuilderResultPath * path)2339 void CheckPathAfterVerification(const CertPathBuilder &path_builder,
2340 CertPathBuilderResultPath *path) override {
2341 path->errors.GetErrorsForCert(2)->AddError(kErrorFromDelegate, nullptr);
2342 }
2343 };
2344
TEST_F(PathBuilderCheckPathAfterVerificationTest,AddsErrorToValidPath)2345 TEST_F(PathBuilderCheckPathAfterVerificationTest, AddsErrorToValidPath) {
2346 AddErrorPathBuilderDelegate delegate;
2347 CertPathBuilder::Result result = RunPathBuilder(nullptr, &delegate);
2348
2349 // Verification failed.
2350 ASSERT_FALSE(result.HasValidPath());
2351
2352 ASSERT_LT(result.best_result_index, result.paths.size());
2353 const CertPathBuilderResultPath *failed_path =
2354 result.paths[result.best_result_index].get();
2355 ASSERT_TRUE(failed_path);
2356
2357 // An error should have been added to certificate at index 2 in the path.
2358 const CertErrors *cert2_errors = failed_path->errors.GetErrorsForCert(2);
2359 ASSERT_TRUE(cert2_errors);
2360 EXPECT_TRUE(cert2_errors->ContainsError(kErrorFromDelegate));
2361
2362 // The newly defined delegate error should map to CERTIFICATE_INVALID
2363 // since it is associated with a certificate (at index 2)
2364 VerifyError error = result.GetBestPathVerifyError();
2365 ASSERT_EQ(error.Code(), VerifyError::StatusCode::CERTIFICATE_INVALID)
2366 << error.DiagnosticString();
2367 }
2368
2369 class AddOtherErrorPathBuilderDelegate : public CertPathBuilderDelegateBase {
2370 public:
CheckPathAfterVerification(const CertPathBuilder & path_builder,CertPathBuilderResultPath * path)2371 void CheckPathAfterVerification(const CertPathBuilder &path_builder,
2372 CertPathBuilderResultPath *path) override {
2373 path->errors.GetOtherErrors()->AddError(kErrorFromDelegate, nullptr);
2374 }
2375 };
2376
TEST_F(PathBuilderCheckPathAfterVerificationTest,AddsErrorToOtherErrors)2377 TEST_F(PathBuilderCheckPathAfterVerificationTest, AddsErrorToOtherErrors) {
2378 AddOtherErrorPathBuilderDelegate delegate;
2379 CertPathBuilder::Result result = RunPathBuilder(nullptr, &delegate);
2380
2381 // Verification failed.
2382 ASSERT_FALSE(result.HasValidPath());
2383
2384 ASSERT_LT(result.best_result_index, result.paths.size());
2385 const CertPathBuilderResultPath *failed_path =
2386 result.paths[result.best_result_index].get();
2387 ASSERT_TRUE(failed_path);
2388
2389 // An error should have been added to other errors
2390 const CertErrors *other_errors = failed_path->errors.GetOtherErrors();
2391 ASSERT_TRUE(other_errors);
2392 EXPECT_TRUE(other_errors->ContainsError(kErrorFromDelegate));
2393
2394 // The newly defined delegate error should map to VERIFICATION_FAILURE
2395 // since the error is not associated to a certificate.
2396 VerifyError error = result.GetBestPathVerifyError();
2397 ASSERT_EQ(error.Code(), VerifyError::StatusCode::VERIFICATION_FAILURE)
2398 << error.DiagnosticString();
2399 }
2400
2401
TEST_F(PathBuilderCheckPathAfterVerificationTest,NoopToAlreadyInvalidPath)2402 TEST_F(PathBuilderCheckPathAfterVerificationTest, NoopToAlreadyInvalidPath) {
2403 StrictMock<MockPathBuilderDelegate> delegate;
2404 // Just verify that the hook is called (on an invalid path).
2405 EXPECT_CALL(delegate, CheckPathAfterVerification(_, _));
2406
2407 // Run the pathbuilder with certificate at index 1 actively distrusted.
2408 CertPathBuilder::Result result = RunPathBuilder(test_.chain[1], &delegate);
2409 EXPECT_FALSE(result.HasValidPath());
2410
2411 VerifyError error = result.GetBestPathVerifyError();
2412 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_NOT_FOUND)
2413 << error.DiagnosticString();
2414 }
2415
2416 struct DelegateData : public CertPathBuilderDelegateData {
2417 int value = 0xB33F;
2418 };
2419
2420 class SetsDelegateDataPathBuilderDelegate : public CertPathBuilderDelegateBase {
2421 public:
CheckPathAfterVerification(const CertPathBuilder & path_builder,CertPathBuilderResultPath * path)2422 void CheckPathAfterVerification(const CertPathBuilder &path_builder,
2423 CertPathBuilderResultPath *path) override {
2424 path->delegate_data = std::make_unique<DelegateData>();
2425 }
2426 };
2427
TEST_F(PathBuilderCheckPathAfterVerificationTest,SetsDelegateData)2428 TEST_F(PathBuilderCheckPathAfterVerificationTest, SetsDelegateData) {
2429 SetsDelegateDataPathBuilderDelegate delegate;
2430 CertPathBuilder::Result result = RunPathBuilder(nullptr, &delegate);
2431 ASSERT_TRUE(result.HasValidPath());
2432
2433 DelegateData *data = reinterpret_cast<DelegateData *>(
2434 result.GetBestValidPath()->delegate_data.get());
2435
2436 EXPECT_EQ(0xB33F, data->value);
2437 }
2438
TEST(PathBuilderPrioritizationTest,DatePrioritization)2439 TEST(PathBuilderPrioritizationTest, DatePrioritization) {
2440 std::string test_dir =
2441 "testdata/path_builder_unittest/validity_date_prioritization/";
2442 std::shared_ptr<const ParsedCertificate> root =
2443 ReadCertFromFile(test_dir + "root.pem");
2444 ASSERT_TRUE(root);
2445 std::shared_ptr<const ParsedCertificate> int_ac =
2446 ReadCertFromFile(test_dir + "int_ac.pem");
2447 ASSERT_TRUE(int_ac);
2448 std::shared_ptr<const ParsedCertificate> int_ad =
2449 ReadCertFromFile(test_dir + "int_ad.pem");
2450 ASSERT_TRUE(int_ad);
2451 std::shared_ptr<const ParsedCertificate> int_bc =
2452 ReadCertFromFile(test_dir + "int_bc.pem");
2453 ASSERT_TRUE(int_bc);
2454 std::shared_ptr<const ParsedCertificate> int_bd =
2455 ReadCertFromFile(test_dir + "int_bd.pem");
2456 ASSERT_TRUE(int_bd);
2457 std::shared_ptr<const ParsedCertificate> target =
2458 ReadCertFromFile(test_dir + "target.pem");
2459 ASSERT_TRUE(target);
2460
2461 SimplePathBuilderDelegate delegate(
2462 1024, SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1);
2463 der::GeneralizedTime verify_time = {2017, 3, 1, 0, 0, 0};
2464
2465 // Distrust the root certificate. This will force the path builder to attempt
2466 // all possible paths.
2467 TrustStoreInMemory trust_store;
2468 trust_store.AddDistrustedCertificateForTest(root);
2469
2470 for (bool reverse_input_order : {false, true}) {
2471 SCOPED_TRACE(reverse_input_order);
2472
2473 CertIssuerSourceStatic intermediates;
2474 // Test with the intermediates supplied in two different orders to ensure
2475 // the results don't depend on input ordering.
2476 if (reverse_input_order) {
2477 intermediates.AddCert(int_bd);
2478 intermediates.AddCert(int_bc);
2479 intermediates.AddCert(int_ad);
2480 intermediates.AddCert(int_ac);
2481 } else {
2482 intermediates.AddCert(int_ac);
2483 intermediates.AddCert(int_ad);
2484 intermediates.AddCert(int_bc);
2485 intermediates.AddCert(int_bd);
2486 }
2487
2488 CertPathBuilder path_builder(
2489 target, &trust_store, &delegate, verify_time, KeyPurpose::ANY_EKU,
2490 InitialExplicitPolicy::kFalse, {der::Input(kAnyPolicyOid)},
2491 InitialPolicyMappingInhibit::kFalse, InitialAnyPolicyInhibit::kFalse);
2492 path_builder.AddCertIssuerSource(&intermediates);
2493
2494 CertPathBuilder::Result result = path_builder.Run();
2495 EXPECT_FALSE(result.HasValidPath());
2496
2497 VerifyError error = result.GetBestPathVerifyError();
2498 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_NOT_FOUND)
2499 << error.DiagnosticString();
2500
2501 ASSERT_EQ(4U, result.paths.size());
2502
2503 // Path builder should have attempted paths using the intermediates in
2504 // order: bd, bc, ad, ac
2505
2506 EXPECT_FALSE(result.paths[0]->IsValid());
2507 ASSERT_EQ(3U, result.paths[0]->certs.size());
2508 EXPECT_EQ(target, result.paths[0]->certs[0]);
2509 EXPECT_EQ(int_bd, result.paths[0]->certs[1]);
2510 EXPECT_EQ(root, result.paths[0]->certs[2]);
2511
2512 EXPECT_FALSE(result.paths[1]->IsValid());
2513 ASSERT_EQ(3U, result.paths[1]->certs.size());
2514 EXPECT_EQ(target, result.paths[1]->certs[0]);
2515 EXPECT_EQ(int_bc, result.paths[1]->certs[1]);
2516 EXPECT_EQ(root, result.paths[1]->certs[2]);
2517
2518 EXPECT_FALSE(result.paths[2]->IsValid());
2519 ASSERT_EQ(3U, result.paths[2]->certs.size());
2520 EXPECT_EQ(target, result.paths[2]->certs[0]);
2521 EXPECT_EQ(int_ad, result.paths[2]->certs[1]);
2522 EXPECT_EQ(root, result.paths[2]->certs[2]);
2523
2524 EXPECT_FALSE(result.paths[3]->IsValid());
2525 ASSERT_EQ(3U, result.paths[3]->certs.size());
2526 EXPECT_EQ(target, result.paths[3]->certs[0]);
2527 EXPECT_EQ(int_ac, result.paths[3]->certs[1]);
2528 EXPECT_EQ(root, result.paths[3]->certs[2]);
2529 }
2530 }
2531
TEST(PathBuilderPrioritizationTest,KeyIdPrioritization)2532 TEST(PathBuilderPrioritizationTest, KeyIdPrioritization) {
2533 std::string test_dir =
2534 "testdata/path_builder_unittest/key_id_prioritization/";
2535 std::shared_ptr<const ParsedCertificate> root =
2536 ReadCertFromFile(test_dir + "root.pem");
2537 ASSERT_TRUE(root);
2538 std::shared_ptr<const ParsedCertificate> int_matching_ski_a =
2539 ReadCertFromFile(test_dir + "int_matching_ski_a.pem");
2540 ASSERT_TRUE(int_matching_ski_a);
2541 std::shared_ptr<const ParsedCertificate> int_matching_ski_b =
2542 ReadCertFromFile(test_dir + "int_matching_ski_b.pem");
2543 ASSERT_TRUE(int_matching_ski_b);
2544 std::shared_ptr<const ParsedCertificate> int_no_ski_a =
2545 ReadCertFromFile(test_dir + "int_no_ski_a.pem");
2546 ASSERT_TRUE(int_no_ski_a);
2547 std::shared_ptr<const ParsedCertificate> int_no_ski_b =
2548 ReadCertFromFile(test_dir + "int_no_ski_b.pem");
2549 ASSERT_TRUE(int_no_ski_b);
2550 std::shared_ptr<const ParsedCertificate> int_different_ski_a =
2551 ReadCertFromFile(test_dir + "int_different_ski_a.pem");
2552 ASSERT_TRUE(int_different_ski_a);
2553 std::shared_ptr<const ParsedCertificate> int_different_ski_b =
2554 ReadCertFromFile(test_dir + "int_different_ski_b.pem");
2555 ASSERT_TRUE(int_different_ski_b);
2556 std::shared_ptr<const ParsedCertificate> target =
2557 ReadCertFromFile(test_dir + "target.pem");
2558 ASSERT_TRUE(target);
2559
2560 SimplePathBuilderDelegate delegate(
2561 1024, SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1);
2562 der::GeneralizedTime verify_time = {2017, 3, 1, 0, 0, 0};
2563
2564 // Distrust the root certificate. This will force the path builder to attempt
2565 // all possible paths.
2566 TrustStoreInMemory trust_store;
2567 trust_store.AddDistrustedCertificateForTest(root);
2568
2569 for (bool reverse_input_order : {false, true}) {
2570 SCOPED_TRACE(reverse_input_order);
2571
2572 CertIssuerSourceStatic intermediates;
2573 // Test with the intermediates supplied in two different orders to ensure
2574 // the results don't depend on input ordering.
2575 if (reverse_input_order) {
2576 intermediates.AddCert(int_different_ski_b);
2577 intermediates.AddCert(int_different_ski_a);
2578 intermediates.AddCert(int_no_ski_b);
2579 intermediates.AddCert(int_no_ski_a);
2580 intermediates.AddCert(int_matching_ski_b);
2581 intermediates.AddCert(int_matching_ski_a);
2582 } else {
2583 intermediates.AddCert(int_matching_ski_a);
2584 intermediates.AddCert(int_matching_ski_b);
2585 intermediates.AddCert(int_no_ski_a);
2586 intermediates.AddCert(int_no_ski_b);
2587 intermediates.AddCert(int_different_ski_a);
2588 intermediates.AddCert(int_different_ski_b);
2589 }
2590
2591 CertPathBuilder path_builder(
2592 target, &trust_store, &delegate, verify_time, KeyPurpose::ANY_EKU,
2593 InitialExplicitPolicy::kFalse, {der::Input(kAnyPolicyOid)},
2594 InitialPolicyMappingInhibit::kFalse, InitialAnyPolicyInhibit::kFalse);
2595 path_builder.AddCertIssuerSource(&intermediates);
2596
2597 CertPathBuilder::Result result = path_builder.Run();
2598 EXPECT_FALSE(result.HasValidPath());
2599 ASSERT_EQ(6U, result.paths.size());
2600
2601 // Path builder should have attempted paths using the intermediates in
2602 // order: matching_ski_b, matching_ski_a, no_ski_b, no_ski_a,
2603 // different_ski_b, different_ski_a
2604
2605 EXPECT_FALSE(result.paths[0]->IsValid());
2606 ASSERT_EQ(3U, result.paths[0]->certs.size());
2607 EXPECT_EQ(target, result.paths[0]->certs[0]);
2608 EXPECT_EQ(int_matching_ski_b, result.paths[0]->certs[1]);
2609 EXPECT_EQ(root, result.paths[0]->certs[2]);
2610
2611 EXPECT_FALSE(result.paths[1]->IsValid());
2612 ASSERT_EQ(3U, result.paths[1]->certs.size());
2613 EXPECT_EQ(target, result.paths[1]->certs[0]);
2614 EXPECT_EQ(int_matching_ski_a, result.paths[1]->certs[1]);
2615 EXPECT_EQ(root, result.paths[1]->certs[2]);
2616
2617 EXPECT_FALSE(result.paths[2]->IsValid());
2618 ASSERT_EQ(3U, result.paths[2]->certs.size());
2619 EXPECT_EQ(target, result.paths[2]->certs[0]);
2620 EXPECT_EQ(int_no_ski_b, result.paths[2]->certs[1]);
2621 EXPECT_EQ(root, result.paths[2]->certs[2]);
2622
2623 EXPECT_FALSE(result.paths[3]->IsValid());
2624 ASSERT_EQ(3U, result.paths[3]->certs.size());
2625 EXPECT_EQ(target, result.paths[3]->certs[0]);
2626 EXPECT_EQ(int_no_ski_a, result.paths[3]->certs[1]);
2627 EXPECT_EQ(root, result.paths[3]->certs[2]);
2628
2629 EXPECT_FALSE(result.paths[4]->IsValid());
2630 ASSERT_EQ(3U, result.paths[4]->certs.size());
2631 EXPECT_EQ(target, result.paths[4]->certs[0]);
2632 EXPECT_EQ(int_different_ski_b, result.paths[4]->certs[1]);
2633 EXPECT_EQ(root, result.paths[4]->certs[2]);
2634
2635 EXPECT_FALSE(result.paths[5]->IsValid());
2636 ASSERT_EQ(3U, result.paths[5]->certs.size());
2637 EXPECT_EQ(target, result.paths[5]->certs[0]);
2638 EXPECT_EQ(int_different_ski_a, result.paths[5]->certs[1]);
2639 EXPECT_EQ(root, result.paths[5]->certs[2]);
2640 }
2641 }
2642
TEST(PathBuilderPrioritizationTest,TrustAndKeyIdPrioritization)2643 TEST(PathBuilderPrioritizationTest, TrustAndKeyIdPrioritization) {
2644 std::string test_dir =
2645 "testdata/path_builder_unittest/key_id_prioritization/";
2646 std::shared_ptr<const ParsedCertificate> root =
2647 ReadCertFromFile(test_dir + "root.pem");
2648 ASSERT_TRUE(root);
2649 std::shared_ptr<const ParsedCertificate> trusted_and_matching =
2650 ReadCertFromFile(test_dir + "int_matching_ski_a.pem");
2651 ASSERT_TRUE(trusted_and_matching);
2652 std::shared_ptr<const ParsedCertificate> matching =
2653 ReadCertFromFile(test_dir + "int_matching_ski_b.pem");
2654 ASSERT_TRUE(matching);
2655 std::shared_ptr<const ParsedCertificate> distrusted_and_matching =
2656 ReadCertFromFile(test_dir + "int_matching_ski_c.pem");
2657 ASSERT_TRUE(distrusted_and_matching);
2658 std::shared_ptr<const ParsedCertificate> trusted_and_no_match_data =
2659 ReadCertFromFile(test_dir + "int_no_ski_a.pem");
2660 ASSERT_TRUE(trusted_and_no_match_data);
2661 std::shared_ptr<const ParsedCertificate> no_match_data =
2662 ReadCertFromFile(test_dir + "int_no_ski_b.pem");
2663 ASSERT_TRUE(no_match_data);
2664 std::shared_ptr<const ParsedCertificate> distrusted_and_no_match_data =
2665 ReadCertFromFile(test_dir + "int_no_ski_c.pem");
2666 ASSERT_TRUE(distrusted_and_no_match_data);
2667 std::shared_ptr<const ParsedCertificate> trusted_and_mismatch =
2668 ReadCertFromFile(test_dir + "int_different_ski_a.pem");
2669 ASSERT_TRUE(trusted_and_mismatch);
2670 std::shared_ptr<const ParsedCertificate> mismatch =
2671 ReadCertFromFile(test_dir + "int_different_ski_b.pem");
2672 ASSERT_TRUE(mismatch);
2673 std::shared_ptr<const ParsedCertificate> distrusted_and_mismatch =
2674 ReadCertFromFile(test_dir + "int_different_ski_c.pem");
2675 ASSERT_TRUE(distrusted_and_mismatch);
2676 std::shared_ptr<const ParsedCertificate> target =
2677 ReadCertFromFile(test_dir + "target.pem");
2678 ASSERT_TRUE(target);
2679
2680 SimplePathBuilderDelegate delegate(
2681 1024, SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1);
2682 der::GeneralizedTime verify_time = {2017, 3, 1, 0, 0, 0};
2683
2684 for (bool reverse_input_order : {false, true}) {
2685 SCOPED_TRACE(reverse_input_order);
2686
2687 TrustStoreInMemory trust_store;
2688 // Test with the intermediates supplied in two different orders to ensure
2689 // the results don't depend on input ordering.
2690 if (reverse_input_order) {
2691 trust_store.AddTrustAnchor(trusted_and_matching);
2692 trust_store.AddCertificateWithUnspecifiedTrust(matching);
2693 trust_store.AddDistrustedCertificateForTest(distrusted_and_matching);
2694 trust_store.AddTrustAnchor(trusted_and_no_match_data);
2695 trust_store.AddCertificateWithUnspecifiedTrust(no_match_data);
2696 trust_store.AddDistrustedCertificateForTest(distrusted_and_no_match_data);
2697 trust_store.AddTrustAnchor(trusted_and_mismatch);
2698 trust_store.AddCertificateWithUnspecifiedTrust(mismatch);
2699 trust_store.AddDistrustedCertificateForTest(distrusted_and_mismatch);
2700 } else {
2701 trust_store.AddDistrustedCertificateForTest(distrusted_and_matching);
2702 trust_store.AddCertificateWithUnspecifiedTrust(no_match_data);
2703 trust_store.AddTrustAnchor(trusted_and_no_match_data);
2704 trust_store.AddTrustAnchor(trusted_and_matching);
2705 trust_store.AddCertificateWithUnspecifiedTrust(matching);
2706 trust_store.AddCertificateWithUnspecifiedTrust(mismatch);
2707 trust_store.AddDistrustedCertificateForTest(distrusted_and_no_match_data);
2708 trust_store.AddTrustAnchor(trusted_and_mismatch);
2709 trust_store.AddDistrustedCertificateForTest(distrusted_and_mismatch);
2710 }
2711 // Also distrust the root certificate. This will force the path builder to
2712 // report paths that included an unspecified trust intermediate.
2713 trust_store.AddDistrustedCertificateForTest(root);
2714
2715 CertPathBuilder path_builder(
2716 target, &trust_store, &delegate, verify_time, KeyPurpose::ANY_EKU,
2717 InitialExplicitPolicy::kFalse, {der::Input(kAnyPolicyOid)},
2718 InitialPolicyMappingInhibit::kFalse, InitialAnyPolicyInhibit::kFalse);
2719 path_builder.SetValidPathLimit(0);
2720
2721 CertPathBuilder::Result result = path_builder.Run();
2722 EXPECT_TRUE(result.HasValidPath());
2723 ASSERT_EQ(9U, result.paths.size());
2724
2725 // Path builder should have attempted paths using the intermediates in
2726 // order: trusted_and_matching, trusted_and_no_match_data, matching,
2727 // no_match_data, trusted_and_mismatch, mismatch, distrusted_and_matching,
2728 // distrusted_and_no_match_data, distrusted_and_mismatch.
2729
2730 EXPECT_TRUE(result.paths[0]->IsValid());
2731 ASSERT_EQ(2U, result.paths[0]->certs.size());
2732 EXPECT_EQ(target, result.paths[0]->certs[0]);
2733 EXPECT_EQ(trusted_and_matching, result.paths[0]->certs[1]);
2734
2735 EXPECT_TRUE(result.paths[1]->IsValid());
2736 ASSERT_EQ(2U, result.paths[1]->certs.size());
2737 EXPECT_EQ(target, result.paths[1]->certs[0]);
2738 EXPECT_EQ(trusted_and_no_match_data, result.paths[1]->certs[1]);
2739
2740 EXPECT_FALSE(result.paths[2]->IsValid());
2741 ASSERT_EQ(3U, result.paths[2]->certs.size());
2742 EXPECT_EQ(target, result.paths[2]->certs[0]);
2743 EXPECT_EQ(matching, result.paths[2]->certs[1]);
2744 EXPECT_EQ(root, result.paths[2]->certs[2]);
2745
2746 EXPECT_FALSE(result.paths[3]->IsValid());
2747 ASSERT_EQ(3U, result.paths[3]->certs.size());
2748 EXPECT_EQ(target, result.paths[3]->certs[0]);
2749 EXPECT_EQ(no_match_data, result.paths[3]->certs[1]);
2750 EXPECT_EQ(root, result.paths[3]->certs[2]);
2751
2752 // Although this intermediate is trusted, it has the wrong key, so
2753 // the path should not be valid.
2754 EXPECT_FALSE(result.paths[4]->IsValid());
2755 ASSERT_EQ(2U, result.paths[4]->certs.size());
2756 EXPECT_EQ(target, result.paths[4]->certs[0]);
2757 EXPECT_EQ(trusted_and_mismatch, result.paths[4]->certs[1]);
2758
2759 EXPECT_FALSE(result.paths[5]->IsValid());
2760 ASSERT_EQ(3U, result.paths[5]->certs.size());
2761 EXPECT_EQ(target, result.paths[5]->certs[0]);
2762 EXPECT_EQ(mismatch, result.paths[5]->certs[1]);
2763 EXPECT_EQ(root, result.paths[5]->certs[2]);
2764
2765 EXPECT_FALSE(result.paths[6]->IsValid());
2766 ASSERT_EQ(2U, result.paths[6]->certs.size());
2767 EXPECT_EQ(target, result.paths[6]->certs[0]);
2768 EXPECT_EQ(distrusted_and_matching, result.paths[6]->certs[1]);
2769
2770 EXPECT_FALSE(result.paths[7]->IsValid());
2771 ASSERT_EQ(2U, result.paths[7]->certs.size());
2772 EXPECT_EQ(target, result.paths[7]->certs[0]);
2773 EXPECT_EQ(distrusted_and_no_match_data, result.paths[7]->certs[1]);
2774
2775 EXPECT_FALSE(result.paths[8]->IsValid());
2776 ASSERT_EQ(2U, result.paths[8]->certs.size());
2777 EXPECT_EQ(target, result.paths[8]->certs[0]);
2778 EXPECT_EQ(distrusted_and_mismatch, result.paths[8]->certs[1]);
2779 }
2780 }
2781
2782 // PathBuilder does not support prioritization based on the issuer name &
2783 // serial in authorityKeyIdentifier, so this test just ensures that it does not
2784 // affect prioritization order and that it is generally just ignored
2785 // completely.
TEST(PathBuilderPrioritizationTest,KeyIdNameAndSerialPrioritization)2786 TEST(PathBuilderPrioritizationTest, KeyIdNameAndSerialPrioritization) {
2787 std::string test_dir =
2788 "testdata/path_builder_unittest/key_id_name_and_serial_prioritization/";
2789 std::shared_ptr<const ParsedCertificate> root =
2790 ReadCertFromFile(test_dir + "root.pem");
2791 ASSERT_TRUE(root);
2792 std::shared_ptr<const ParsedCertificate> root2 =
2793 ReadCertFromFile(test_dir + "root2.pem");
2794 ASSERT_TRUE(root2);
2795 std::shared_ptr<const ParsedCertificate> int_matching =
2796 ReadCertFromFile(test_dir + "int_matching.pem");
2797 ASSERT_TRUE(int_matching);
2798 std::shared_ptr<const ParsedCertificate> int_match_name_only =
2799 ReadCertFromFile(test_dir + "int_match_name_only.pem");
2800 ASSERT_TRUE(int_match_name_only);
2801 std::shared_ptr<const ParsedCertificate> int_mismatch =
2802 ReadCertFromFile(test_dir + "int_mismatch.pem");
2803 ASSERT_TRUE(int_mismatch);
2804 std::shared_ptr<const ParsedCertificate> target =
2805 ReadCertFromFile(test_dir + "target.pem");
2806 ASSERT_TRUE(target);
2807
2808 SimplePathBuilderDelegate delegate(
2809 1024, SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1);
2810 der::GeneralizedTime verify_time = {2017, 3, 1, 0, 0, 0};
2811
2812 // Distrust the root certificates. This will force the path builder to attempt
2813 // all possible paths.
2814 TrustStoreInMemory trust_store;
2815 trust_store.AddDistrustedCertificateForTest(root);
2816 trust_store.AddDistrustedCertificateForTest(root2);
2817
2818 for (bool reverse_input_order : {false, true}) {
2819 SCOPED_TRACE(reverse_input_order);
2820
2821 CertIssuerSourceStatic intermediates;
2822 // Test with the intermediates supplied in two different orders to ensure
2823 // the results don't depend on input ordering.
2824 if (reverse_input_order) {
2825 intermediates.AddCert(int_mismatch);
2826 intermediates.AddCert(int_match_name_only);
2827 intermediates.AddCert(int_matching);
2828 } else {
2829 intermediates.AddCert(int_matching);
2830 intermediates.AddCert(int_match_name_only);
2831 intermediates.AddCert(int_mismatch);
2832 }
2833
2834 CertPathBuilder path_builder(
2835 target, &trust_store, &delegate, verify_time, KeyPurpose::ANY_EKU,
2836 InitialExplicitPolicy::kFalse, {der::Input(kAnyPolicyOid)},
2837 InitialPolicyMappingInhibit::kFalse, InitialAnyPolicyInhibit::kFalse);
2838 path_builder.AddCertIssuerSource(&intermediates);
2839
2840 CertPathBuilder::Result result = path_builder.Run();
2841 EXPECT_FALSE(result.HasValidPath());
2842 ASSERT_EQ(3U, result.paths.size());
2843 VerifyError error = result.GetBestPathVerifyError();
2844 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_NOT_FOUND)
2845 << error.DiagnosticString();
2846
2847 // The serial & issuer method is not used in prioritization, so the certs
2848 // should have been prioritized based on dates. The test certs have the
2849 // date priority order in the reverse of what authorityKeyIdentifier
2850 // prioritization would have done if it were supported.
2851 // Path builder should have attempted paths using the intermediates in
2852 // order: mismatch, match_name_only, matching
2853
2854 EXPECT_FALSE(result.paths[0]->IsValid());
2855 ASSERT_EQ(3U, result.paths[0]->certs.size());
2856 EXPECT_EQ(target, result.paths[0]->certs[0]);
2857 EXPECT_EQ(int_mismatch, result.paths[0]->certs[1]);
2858 EXPECT_EQ(root2, result.paths[0]->certs[2]);
2859
2860 EXPECT_FALSE(result.paths[1]->IsValid());
2861 ASSERT_EQ(3U, result.paths[1]->certs.size());
2862 EXPECT_EQ(target, result.paths[1]->certs[0]);
2863 EXPECT_EQ(int_match_name_only, result.paths[1]->certs[1]);
2864 EXPECT_EQ(root, result.paths[1]->certs[2]);
2865
2866 EXPECT_FALSE(result.paths[2]->IsValid());
2867 ASSERT_EQ(3U, result.paths[2]->certs.size());
2868 EXPECT_EQ(target, result.paths[2]->certs[0]);
2869 EXPECT_EQ(int_matching, result.paths[2]->certs[1]);
2870 EXPECT_EQ(root, result.paths[2]->certs[2]);
2871 }
2872 }
2873
TEST(PathBuilderPrioritizationTest,SelfIssuedPrioritization)2874 TEST(PathBuilderPrioritizationTest, SelfIssuedPrioritization) {
2875 std::string test_dir =
2876 "testdata/path_builder_unittest/self_issued_prioritization/";
2877 std::shared_ptr<const ParsedCertificate> root1 =
2878 ReadCertFromFile(test_dir + "root1.pem");
2879 ASSERT_TRUE(root1);
2880 std::shared_ptr<const ParsedCertificate> root1_cross =
2881 ReadCertFromFile(test_dir + "root1_cross.pem");
2882 ASSERT_TRUE(root1_cross);
2883 std::shared_ptr<const ParsedCertificate> target =
2884 ReadCertFromFile(test_dir + "target.pem");
2885 ASSERT_TRUE(target);
2886
2887 SimplePathBuilderDelegate delegate(
2888 1024, SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1);
2889 der::GeneralizedTime verify_time = {2017, 3, 1, 0, 0, 0};
2890
2891 TrustStoreInMemory trust_store;
2892 trust_store.AddTrustAnchor(root1);
2893 trust_store.AddTrustAnchor(root1_cross);
2894 CertPathBuilder path_builder(
2895 target, &trust_store, &delegate, verify_time, KeyPurpose::ANY_EKU,
2896 InitialExplicitPolicy::kFalse, {der::Input(kAnyPolicyOid)},
2897 InitialPolicyMappingInhibit::kFalse, InitialAnyPolicyInhibit::kFalse);
2898 path_builder.SetValidPathLimit(0);
2899
2900 CertPathBuilder::Result result = path_builder.Run();
2901 EXPECT_TRUE(result.HasValidPath());
2902 VerifyError error = result.GetBestPathVerifyError();
2903 ASSERT_EQ(error.Code(), VerifyError::StatusCode::PATH_VERIFIED)
2904 << error.DiagnosticString();
2905
2906 // Path builder should have built paths to both trusted roots.
2907 ASSERT_EQ(2U, result.paths.size());
2908
2909 // |root1| should have been preferred because it is self-issued, even though
2910 // the notBefore date is older than |root1_cross|.
2911 EXPECT_TRUE(result.paths[0]->IsValid());
2912 ASSERT_EQ(2U, result.paths[0]->certs.size());
2913 EXPECT_EQ(target, result.paths[0]->certs[0]);
2914 EXPECT_EQ(root1, result.paths[0]->certs[1]);
2915
2916 EXPECT_TRUE(result.paths[1]->IsValid());
2917 ASSERT_EQ(2U, result.paths[1]->certs.size());
2918 EXPECT_EQ(target, result.paths[1]->certs[0]);
2919 EXPECT_EQ(root1_cross, result.paths[1]->certs[1]);
2920 }
2921
2922 } // namespace
2923
2924 } // namespace bssl
2925