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