Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(124)

Side by Side Diff: net/cert/internal/path_builder_unittest.cc

Issue 1923433002: Certificate path builder for new certificate verification library (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: changes for review comment #20 Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/cert/internal/path_builder.h"
6
7 #include "base/base_paths.h"
8 #include "base/cancelable_callback.h"
9 #include "base/files/file_util.h"
10 #include "base/location.h"
11 #include "base/path_service.h"
12 #include "base/threading/thread_task_runner_handle.h"
13 #include "net/base/net_errors.h"
14 #include "net/base/test_completion_callback.h"
15 #include "net/cert/internal/cert_issuer_source_static.h"
16 #include "net/cert/internal/parsed_certificate.h"
17 #include "net/cert/internal/signature_policy.h"
18 #include "net/cert/internal/test_helpers.h"
19 #include "net/cert/internal/trust_store.h"
20 #include "net/cert/internal/verify_certificate_chain.h"
21 #include "net/cert/pem_tokenizer.h"
22 #include "net/der/input.h"
23 #include "net/test/cert_test_util.h"
24 #include "net/test/test_certificate_data.h"
25 #include "testing/gmock/include/gmock/gmock.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27
28 namespace net {
29
30 namespace {
31
32 using ::testing::_;
33 using ::testing::Invoke;
34 using ::testing::SaveArg;
35 using ::testing::StrictMock;
36 using ::testing::SetArgPointee;
37 using ::testing::Return;
38
39 // AsyncCertIssuerSourceStatic always returns its certs asynchronously.
40 class AsyncCertIssuerSourceStatic : public CertIssuerSource {
41 public:
42 class StaticAsyncRequest : public Request {
43 public:
44 StaticAsyncRequest(const IssuerCallback& issuers_callback,
45 ParsedCertificateList&& issuers)
46 : cancelable_closure_(base::Bind(&StaticAsyncRequest::RunCallback,
47 base::Unretained(this))),
48 issuers_callback_(issuers_callback) {
49 issuers_.swap(issuers);
50 issuers_iter_ = issuers_.begin();
51 }
52 ~StaticAsyncRequest() override {}
53
54 CompletionStatus GetNext(
55 scoped_refptr<ParsedCertificate>* out_cert) override {
56 if (issuers_iter_ == issuers_.end())
57 *out_cert = nullptr;
58 else
59 *out_cert = std::move(*issuers_iter_++);
60 return CompletionStatus::SYNC;
61 }
62
63 base::Closure callback() { return cancelable_closure_.callback(); }
64
65 private:
66 void RunCallback() { issuers_callback_.Run(this); }
67
68 base::CancelableClosure cancelable_closure_;
69 IssuerCallback issuers_callback_;
70 ParsedCertificateList issuers_;
71 ParsedCertificateList::iterator issuers_iter_;
72
73 DISALLOW_COPY_AND_ASSIGN(StaticAsyncRequest);
74 };
75
76 ~AsyncCertIssuerSourceStatic() override {}
77
78 void AddCert(scoped_refptr<ParsedCertificate> cert) {
79 static_cert_issuer_source_.AddCert(std::move(cert));
80 }
81
82 void SyncGetIssuersOf(const ParsedCertificate* cert,
83 ParsedCertificateList* issuers) override {}
84 void AsyncGetIssuersOf(const ParsedCertificate* cert,
85 const IssuerCallback& issuers_callback,
86 std::unique_ptr<Request>* out_req) override {
87 num_async_gets_++;
88 ParsedCertificateList issuers;
89 static_cert_issuer_source_.SyncGetIssuersOf(cert, &issuers);
90 std::unique_ptr<StaticAsyncRequest> req(
91 new StaticAsyncRequest(issuers_callback, std::move(issuers)));
92 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, req->callback());
93 *out_req = std::move(req);
94 }
95 int num_async_gets() const { return num_async_gets_; }
96
97 private:
98 CertIssuerSourceStatic static_cert_issuer_source_;
99
100 int num_async_gets_ = 0;
101 };
102
103 // Reads a data file from the unit-test data.
104 std::string ReadTestFileToString(const std::string& file_name) {
105 // Compute the full path, relative to the src/ directory.
106 base::FilePath src_root;
107 PathService::Get(base::DIR_SOURCE_ROOT, &src_root);
108 base::FilePath filepath = src_root.AppendASCII(file_name);
109
110 // Read the full contents of the file.
111 std::string file_data;
112 if (!base::ReadFileToString(filepath, &file_data)) {
113 ADD_FAILURE() << "Couldn't read file: " << filepath.value();
114 return std::string();
115 }
116
117 return file_data;
118 }
119
120 // Reads a verify_certificate_chain_unittest-style test case from |file_name|.
121 // Test cases are comprised of a certificate chain, trust store, a timestamp to
122 // validate at, and the expected result of verification (though the expected
123 // result is ignored here).
124 void ReadVerifyCertChainTestFromFile(const std::string& file_name,
125 std::vector<std::string>* chain,
126 scoped_refptr<ParsedCertificate>* root,
127 der::GeneralizedTime* time) {
128 chain->clear();
129
130 std::string file_data = ReadTestFileToString(file_name);
131
132 std::vector<std::string> pem_headers;
133
134 const char kCertificateHeader[] = "CERTIFICATE";
135 const char kTrustedCertificateHeader[] = "TRUSTED_CERTIFICATE";
136 const char kTimeHeader[] = "TIME";
137
138 pem_headers.push_back(kCertificateHeader);
139 pem_headers.push_back(kTrustedCertificateHeader);
140 pem_headers.push_back(kTimeHeader);
141
142 bool has_time = false;
143
144 PEMTokenizer pem_tokenizer(file_data, pem_headers);
145 while (pem_tokenizer.GetNext()) {
146 const std::string& block_type = pem_tokenizer.block_type();
147 const std::string& block_data = pem_tokenizer.data();
148
149 if (block_type == kCertificateHeader) {
150 chain->push_back(block_data);
151 } else if (block_type == kTrustedCertificateHeader) {
152 *root = ParsedCertificate::CreateFromCertificateCopy(block_data, {});
153 ASSERT_TRUE(*root);
154 } else if (block_type == kTimeHeader) {
155 ASSERT_FALSE(has_time) << "Duplicate " << kTimeHeader;
156 has_time = true;
157 ASSERT_TRUE(der::ParseUTCTime(der::Input(&block_data), time));
158 }
159 }
160
161 ASSERT_TRUE(has_time);
162 }
163
164 ::testing::AssertionResult ReadTestPem(const std::string& file_name,
165 const std::string& block_name,
166 std::string* result) {
167 const PemBlockMapping mappings[] = {
168 {block_name.c_str(), result},
169 };
170
171 return ReadTestDataFromPemFile(file_name, mappings);
172 }
173
174 ::testing::AssertionResult ReadTestCert(
175 const std::string& file_name,
176 scoped_refptr<ParsedCertificate>* result) {
177 std::string der;
178 ::testing::AssertionResult r = ReadTestPem(
179 "net/data/ssl/certificates/" + file_name, "CERTIFICATE", &der);
180 if (!r)
181 return r;
182 *result = ParsedCertificate::CreateFromCertificateCopy(der, {});
183 if (!*result)
184 return ::testing::AssertionFailure() << "CreateFromCertificateCopy failed";
185 return ::testing::AssertionSuccess();
186 }
187
188 // Run the path builder, and wait for async completion if necessary. The return
189 // value signifies whether the path builder completed synchronously or
190 // asynchronously, not that RunPathBuilder itself is asynchronous.
191 CompletionStatus RunPathBuilder(CertPathBuilder* path_builder) {
192 TestClosure callback;
193 CompletionStatus rv = path_builder->Run(callback.closure());
194
195 if (rv == CompletionStatus::ASYNC) {
196 DVLOG(1) << "waiting for async completion...";
197 callback.WaitForResult();
198 DVLOG(1) << "async completed.";
199 }
200 return rv;
201 }
202
203 class PathBuilderMultiRootTest : public ::testing::Test {
204 public:
205 PathBuilderMultiRootTest() : signature_policy_(1024) {}
206
207 void SetUp() override {
208 ASSERT_TRUE(ReadTestCert("multi-root-A-by-B.pem", &a_by_b_));
209 ASSERT_TRUE(ReadTestCert("multi-root-B-by-C.pem", &b_by_c_));
210 ASSERT_TRUE(ReadTestCert("multi-root-B-by-F.pem", &b_by_f_));
211 ASSERT_TRUE(ReadTestCert("multi-root-C-by-D.pem", &c_by_d_));
212 ASSERT_TRUE(ReadTestCert("multi-root-C-by-E.pem", &c_by_e_));
213 ASSERT_TRUE(ReadTestCert("multi-root-D-by-D.pem", &d_by_d_));
214 ASSERT_TRUE(ReadTestCert("multi-root-E-by-E.pem", &e_by_e_));
215 ASSERT_TRUE(ReadTestCert("multi-root-F-by-E.pem", &f_by_e_));
216 }
217
218 protected:
219 scoped_refptr<ParsedCertificate> a_by_b_, b_by_c_, b_by_f_, c_by_d_, c_by_e_,
220 d_by_d_, e_by_e_, f_by_e_;
221
222 SimpleSignaturePolicy signature_policy_;
223 der::GeneralizedTime time_ = {2016, 4, 11, 0, 0, 0};
224 };
225
226 // If the target cert is a trust anchor, it should verify and should not include
227 // anything else in the path.
228 TEST_F(PathBuilderMultiRootTest, TargetIsTrustAnchor) {
229 TrustStore trust_store;
230 trust_store.AddTrustedCertificate(a_by_b_);
231 trust_store.AddTrustedCertificate(b_by_f_);
232
233 CertPathBuilder::Result result;
234 CertPathBuilder path_builder(a_by_b_, &trust_store, &signature_policy_, time_,
235 &result);
236
237 EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
238
239 EXPECT_EQ(OK, result.error());
240 EXPECT_EQ(1U, result.paths[result.best_result_index]->path.size());
241 EXPECT_EQ(a_by_b_, result.paths[result.best_result_index]->path[0]);
242 }
243
244 // If the target cert is directly issued by a trust anchor, it should verify
245 // without any intermediate certs being provided.
246 TEST_F(PathBuilderMultiRootTest, TargetDirectlySignedByTrustAnchor) {
247 TrustStore trust_store;
248 trust_store.AddTrustedCertificate(b_by_f_);
249
250 CertPathBuilder::Result result;
251 CertPathBuilder path_builder(a_by_b_, &trust_store, &signature_policy_, time_,
252 &result);
253
254 EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
255
256 EXPECT_EQ(OK, result.error());
257 EXPECT_EQ(2U, result.paths[result.best_result_index]->path.size());
258 EXPECT_EQ(a_by_b_, result.paths[result.best_result_index]->path[0]);
259 EXPECT_EQ(b_by_f_, result.paths[result.best_result_index]->path[1]);
260 }
261
262 // Test that async cert queries are not made if the path can be successfully
263 // built with synchronously available certs.
264 TEST_F(PathBuilderMultiRootTest, TriesSyncFirst) {
265 TrustStore trust_store;
266 trust_store.AddTrustedCertificate(e_by_e_);
267
268 CertIssuerSourceStatic sync_certs;
269 sync_certs.AddCert(b_by_f_);
270 sync_certs.AddCert(f_by_e_);
271
272 AsyncCertIssuerSourceStatic async_certs;
273 async_certs.AddCert(b_by_c_);
274 async_certs.AddCert(c_by_e_);
275
276 CertPathBuilder::Result result;
277 CertPathBuilder path_builder(a_by_b_, &trust_store, &signature_policy_, time_,
278 &result);
279 path_builder.AddCertIssuerSource(&async_certs);
280 path_builder.AddCertIssuerSource(&sync_certs);
281
282 EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
283
284 EXPECT_EQ(OK, result.error());
285 EXPECT_EQ(0, async_certs.num_async_gets());
286 }
287
288 // Test that async cert queries are not made if no callback is provided.
289 TEST_F(PathBuilderMultiRootTest, SychronousOnlyMode) {
290 TrustStore trust_store;
291 trust_store.AddTrustedCertificate(e_by_e_);
292
293 CertIssuerSourceStatic sync_certs;
294 sync_certs.AddCert(f_by_e_);
295
296 AsyncCertIssuerSourceStatic async_certs;
297 async_certs.AddCert(b_by_f_);
298
299 CertPathBuilder::Result result;
300 CertPathBuilder path_builder(a_by_b_, &trust_store, &signature_policy_, time_,
301 &result);
302 path_builder.AddCertIssuerSource(&async_certs);
303 path_builder.AddCertIssuerSource(&sync_certs);
304
305 EXPECT_EQ(CompletionStatus::SYNC, path_builder.Run(base::Closure()));
306
307 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.error());
308 EXPECT_EQ(0, async_certs.num_async_gets());
309 }
310
311 // If async queries are needed, all async sources will be queried
312 // simultaneously.
313 TEST_F(PathBuilderMultiRootTest, TestAsyncSimultaneous) {
314 TrustStore trust_store;
315 trust_store.AddTrustedCertificate(e_by_e_);
316
317 CertIssuerSourceStatic sync_certs;
318 sync_certs.AddCert(b_by_c_);
319 sync_certs.AddCert(b_by_f_);
320
321 AsyncCertIssuerSourceStatic async_certs1;
322 async_certs1.AddCert(c_by_e_);
323
324 AsyncCertIssuerSourceStatic async_certs2;
325 async_certs2.AddCert(f_by_e_);
326
327 CertPathBuilder::Result result;
328 CertPathBuilder path_builder(a_by_b_, &trust_store, &signature_policy_, time_,
329 &result);
330 path_builder.AddCertIssuerSource(&async_certs1);
331 path_builder.AddCertIssuerSource(&async_certs2);
332 path_builder.AddCertIssuerSource(&sync_certs);
333
334 EXPECT_EQ(CompletionStatus::ASYNC, RunPathBuilder(&path_builder));
335
336 EXPECT_EQ(OK, result.error());
337 EXPECT_EQ(1, async_certs1.num_async_gets());
338 EXPECT_EQ(1, async_certs2.num_async_gets());
339 }
340
341 // Test that PathBuilder does not generate longer paths than necessary if one of
342 // the supplied certs is itself a trust anchor.
343 TEST_F(PathBuilderMultiRootTest, TestLongChain) {
344 // Both D(D) and C(D) are trusted roots.
345 TrustStore trust_store;
346 trust_store.AddTrustedCertificate(d_by_d_);
347 trust_store.AddTrustedCertificate(c_by_d_);
348
349 // Certs B(C), and C(D) are all supplied.
350 CertIssuerSourceStatic sync_certs;
351 sync_certs.AddCert(b_by_c_);
352 sync_certs.AddCert(c_by_d_);
353
354 CertPathBuilder::Result result;
355 CertPathBuilder path_builder(a_by_b_, &trust_store, &signature_policy_, time_,
356 &result);
357 path_builder.AddCertIssuerSource(&sync_certs);
358
359 EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
360
361 EXPECT_EQ(OK, result.error());
362
363 // The result path should be A(B) <- B(C) <- C(D)
364 // not the longer but also valid A(B) <- B(C) <- C(D) <- D(D)
365 EXPECT_EQ(3U, result.paths[result.best_result_index]->path.size());
366 }
367
368 // Test that PathBuilder will backtrack and try a different path if the first
369 // one doesn't work out.
370 TEST_F(PathBuilderMultiRootTest, TestBacktracking) {
371 // Only D(D) is a trusted root.
372 TrustStore trust_store;
373 trust_store.AddTrustedCertificate(d_by_d_);
374
375 // Certs B(F) and F(E) are supplied synchronously, thus the path
376 // A(B) <- B(F) <- F(E) should be built first, though it won't verify.
377 CertIssuerSourceStatic sync_certs;
378 sync_certs.AddCert(b_by_f_);
379 sync_certs.AddCert(f_by_e_);
380
381 // Certs B(C), and C(D) are supplied asynchronously, so the path
382 // A(B) <- B(C) <- C(D) <- D(D) should be tried second.
383 AsyncCertIssuerSourceStatic async_certs;
384 async_certs.AddCert(b_by_c_);
385 async_certs.AddCert(c_by_d_);
386
387 CertPathBuilder::Result result;
388 CertPathBuilder path_builder(a_by_b_, &trust_store, &signature_policy_, time_,
389 &result);
390 path_builder.AddCertIssuerSource(&sync_certs);
391 path_builder.AddCertIssuerSource(&async_certs);
392
393 EXPECT_EQ(CompletionStatus::ASYNC, RunPathBuilder(&path_builder));
394
395 EXPECT_EQ(OK, result.error());
396
397 // The result path should be A(B) <- B(C) <- C(D) <- D(D)
398 ASSERT_EQ(4U, result.paths[result.best_result_index]->path.size());
399 EXPECT_EQ(a_by_b_, result.paths[result.best_result_index]->path[0]);
400 EXPECT_EQ(b_by_c_, result.paths[result.best_result_index]->path[1]);
401 EXPECT_EQ(c_by_d_, result.paths[result.best_result_index]->path[2]);
402 EXPECT_EQ(d_by_d_, result.paths[result.best_result_index]->path[3]);
403 }
404
405 // Test that whichever order CertIssuerSource returns the issuers, the path
406 // building still succeeds.
407 TEST_F(PathBuilderMultiRootTest, TestCertIssuerOrdering) {
408 // Only D(D) is a trusted root.
409 TrustStore trust_store;
410 trust_store.AddTrustedCertificate(d_by_d_);
411
412 for (bool reverse_order : {false, true}) {
413 SCOPED_TRACE(reverse_order);
414 std::vector<scoped_refptr<ParsedCertificate>> certs = {
415 b_by_c_, b_by_f_, f_by_e_, c_by_d_, c_by_e_};
416 CertIssuerSourceStatic sync_certs;
417 if (reverse_order) {
418 for (auto it = certs.rbegin(); it != certs.rend(); ++it)
419 sync_certs.AddCert(*it);
420 } else {
421 for (const auto& cert : certs)
422 sync_certs.AddCert(cert);
423 }
424
425 CertPathBuilder::Result result;
426 CertPathBuilder path_builder(a_by_b_, &trust_store, &signature_policy_,
427 time_, &result);
428 path_builder.AddCertIssuerSource(&sync_certs);
429
430 EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
431
432 EXPECT_EQ(OK, result.error());
433
434 // The result path should be A(B) <- B(C) <- C(D) <- D(D)
435 ASSERT_EQ(4U, result.paths[result.best_result_index]->path.size());
436 EXPECT_EQ(a_by_b_, result.paths[result.best_result_index]->path[0]);
437 EXPECT_EQ(b_by_c_, result.paths[result.best_result_index]->path[1]);
438 EXPECT_EQ(c_by_d_, result.paths[result.best_result_index]->path[2]);
439 EXPECT_EQ(d_by_d_, result.paths[result.best_result_index]->path[3]);
440 }
441 }
442
443 class PathBuilderKeyRolloverTest : public ::testing::Test {
444 public:
445 PathBuilderKeyRolloverTest() : signature_policy_(1024) {}
446
447 void SetUp() override {
448 std::vector<std::string> path;
449
450 ReadVerifyCertChainTestFromFile(
451 "net/data/verify_certificate_chain_unittest/key-rollover-oldchain.pem",
452 &path, &oldroot_, &time_);
453 ASSERT_EQ(2U, path.size());
454 target_ = ParsedCertificate::CreateFromCertificateCopy(path[0], {});
455 oldintermediate_ =
456 ParsedCertificate::CreateFromCertificateCopy(path[1], {});
457 ASSERT_TRUE(target_);
458 ASSERT_TRUE(oldintermediate_);
459
460 ReadVerifyCertChainTestFromFile(
461 "net/data/verify_certificate_chain_unittest/"
462 "key-rollover-longrolloverchain.pem",
463 &path, &oldroot_, &time_);
464 ASSERT_EQ(4U, path.size());
465 newintermediate_ =
466 ParsedCertificate::CreateFromCertificateCopy(path[1], {});
467 newroot_ = ParsedCertificate::CreateFromCertificateCopy(path[2], {});
468 newrootrollover_ =
469 ParsedCertificate::CreateFromCertificateCopy(path[3], {});
470 ASSERT_TRUE(newintermediate_);
471 ASSERT_TRUE(newroot_);
472 ASSERT_TRUE(newrootrollover_);
473 }
474
475 protected:
476 // oldroot-------->newrootrollover newroot
477 // | | |
478 // v v v
479 // oldintermediate newintermediate
480 // | |
481 // +------------+-------------+
482 // |
483 // v
484 // target
485 scoped_refptr<ParsedCertificate> target_;
486 scoped_refptr<ParsedCertificate> oldintermediate_;
487 scoped_refptr<ParsedCertificate> newintermediate_;
488 scoped_refptr<ParsedCertificate> oldroot_;
489 scoped_refptr<ParsedCertificate> newroot_;
490 scoped_refptr<ParsedCertificate> newrootrollover_;
491
492 SimpleSignaturePolicy signature_policy_;
493 der::GeneralizedTime time_;
494 };
495
496 // Tests that if only the old root cert is trusted, the path builder can build a
497 // path through the new intermediate and rollover cert to the old root.
498 TEST_F(PathBuilderKeyRolloverTest, TestRolloverOnlyOldRootTrusted) {
499 // Only oldroot is trusted.
500 TrustStore trust_store;
501 trust_store.AddTrustedCertificate(oldroot_);
502
503 // Old intermediate cert is not provided, so the pathbuilder will need to go
504 // through the rollover cert.
505 CertIssuerSourceStatic sync_certs;
506 sync_certs.AddCert(newintermediate_);
507 sync_certs.AddCert(newrootrollover_);
508
509 CertPathBuilder::Result result;
510 CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_,
511 &result);
512 path_builder.AddCertIssuerSource(&sync_certs);
513
514 EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
515
516 EXPECT_EQ(OK, result.error());
517
518 // Path builder will first attempt: target <- newintermediate <- oldroot
519 // but it will fail since newintermediate is signed by newroot.
520 ASSERT_EQ(2U, result.paths.size());
521 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.paths[0]->error);
522 ASSERT_EQ(3U, result.paths[0]->path.size());
523 EXPECT_EQ(target_, result.paths[0]->path[0]);
524 EXPECT_EQ(newintermediate_, result.paths[0]->path[1]);
525 EXPECT_EQ(oldroot_, result.paths[0]->path[2]);
526
527 // Path builder will next attempt:
528 // target <- newintermediate <- newrootrollover <- oldroot
529 // which will succeed.
530 EXPECT_EQ(1U, result.best_result_index);
531 EXPECT_EQ(OK, result.paths[1]->error);
532 ASSERT_EQ(4U, result.paths[1]->path.size());
533 EXPECT_EQ(target_, result.paths[1]->path[0]);
534 EXPECT_EQ(newintermediate_, result.paths[1]->path[1]);
535 EXPECT_EQ(newrootrollover_, result.paths[1]->path[2]);
536 EXPECT_EQ(oldroot_, result.paths[1]->path[3]);
537 }
538
539 // Tests that if both old and new roots are trusted it can build a path through
540 // either.
541 // TODO(mattm): Once prioritization is implemented, it should test that it
542 // always builds the path through the new intermediate and new root.
543 TEST_F(PathBuilderKeyRolloverTest, TestRolloverBothRootsTrusted) {
544 // Both oldroot and newroot are trusted.
545 TrustStore trust_store;
546 trust_store.AddTrustedCertificate(oldroot_);
547 trust_store.AddTrustedCertificate(newroot_);
548
549 // Both old and new intermediates + rollover cert are provided.
550 CertIssuerSourceStatic sync_certs;
551 sync_certs.AddCert(oldintermediate_);
552 sync_certs.AddCert(newintermediate_);
553 sync_certs.AddCert(newrootrollover_);
554
555 CertPathBuilder::Result result;
556 CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_,
557 &result);
558 path_builder.AddCertIssuerSource(&sync_certs);
559
560 EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
561
562 EXPECT_EQ(OK, result.error());
563
564 // Path builder willattempt one of:
565 // target <- oldintermediate <- oldroot
566 // target <- newintermediate <- newroot
567 // either will succeed.
568 ASSERT_EQ(1U, result.paths.size());
569 EXPECT_EQ(OK, result.paths[0]->error);
570 ASSERT_EQ(3U, result.paths[0]->path.size());
571 EXPECT_EQ(target_, result.paths[0]->path[0]);
572 if (result.paths[0]->path[1] != newintermediate_) {
573 DVLOG(1) << "USED OLD";
574 EXPECT_EQ(oldintermediate_, result.paths[0]->path[1]);
575 EXPECT_EQ(oldroot_, result.paths[0]->path[2]);
576 } else {
577 DVLOG(1) << "USED NEW";
578 EXPECT_EQ(newintermediate_, result.paths[0]->path[1]);
579 EXPECT_EQ(newroot_, result.paths[0]->path[2]);
580 }
581 }
582
583 // Tests that multiple trust root matches on a single path will be considered.
584 // Both roots have the same subject but different keys. Only one of them will
585 // verify.
586 TEST_F(PathBuilderKeyRolloverTest, TestMultipleRootMatchesOnlyOneWorks) {
587 // Both newroot and oldroot are trusted.
588 TrustStore trust_store;
589 // Note: The test assumes newroot will be tried before oldroot.
590 // Currently this depends on the order the roots are added.
591 trust_store.AddTrustedCertificate(newroot_);
592 trust_store.AddTrustedCertificate(oldroot_);
593
594 // Only oldintermediate is supplied, so the path with newroot should fail,
595 // oldroot should succeed.
596 CertIssuerSourceStatic sync_certs;
597 sync_certs.AddCert(oldintermediate_);
598
599 CertPathBuilder::Result result;
600 CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_,
601 &result);
602 path_builder.AddCertIssuerSource(&sync_certs);
603
604 EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
605
606 EXPECT_EQ(OK, result.error());
607 ASSERT_EQ(2U, result.paths.size());
608
609 // Path builder will first attempt: target <- oldintermediate <- newroot
610 // but it will fail since oldintermediate is signed by oldroot.
611 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.paths[0]->error);
612 ASSERT_EQ(3U, result.paths[0]->path.size());
613 EXPECT_EQ(target_, result.paths[0]->path[0]);
614 EXPECT_EQ(oldintermediate_, result.paths[0]->path[1]);
615 EXPECT_EQ(newroot_, result.paths[0]->path[2]);
616
617 // Path builder will next attempt:
618 // target <- old intermediate <- oldroot
619 // which should succeed.
620 EXPECT_EQ(OK, result.paths[1]->error);
621 ASSERT_EQ(3U, result.paths[1]->path.size());
622 EXPECT_EQ(target_, result.paths[1]->path[0]);
623 EXPECT_EQ(oldintermediate_, result.paths[1]->path[1]);
624 EXPECT_EQ(oldroot_, result.paths[1]->path[2]);
625 }
626
627 // Tests that the path builder doesn't build longer than necessary paths.
628 TEST_F(PathBuilderKeyRolloverTest, TestRolloverLongChain) {
629 // Only oldroot is trusted.
630 TrustStore trust_store;
631 trust_store.AddTrustedCertificate(oldroot_);
632
633 // New intermediate and new root are provided synchronously.
634 CertIssuerSourceStatic sync_certs;
635 sync_certs.AddCert(newintermediate_);
636 sync_certs.AddCert(newroot_);
637
638 // Rollover cert is only provided asynchronously. This will force the
639 // pathbuilder to first try building a longer than necessary path.
640 AsyncCertIssuerSourceStatic async_certs;
641 async_certs.AddCert(newrootrollover_);
642
643 CertPathBuilder::Result result;
644 CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_,
645 &result);
646 path_builder.AddCertIssuerSource(&sync_certs);
647 path_builder.AddCertIssuerSource(&async_certs);
648
649 EXPECT_EQ(CompletionStatus::ASYNC, RunPathBuilder(&path_builder));
650
651 EXPECT_EQ(OK, result.error());
652 ASSERT_EQ(3U, result.paths.size());
653
654 // Path builder will first attempt: target <- newintermediate <- oldroot
655 // but it will fail since newintermediate is signed by newroot.
656 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.paths[0]->error);
657 ASSERT_EQ(3U, result.paths[0]->path.size());
658 EXPECT_EQ(target_, result.paths[0]->path[0]);
659 EXPECT_EQ(newintermediate_, result.paths[0]->path[1]);
660 EXPECT_EQ(oldroot_, result.paths[0]->path[2]);
661
662 // Path builder will next attempt:
663 // target <- newintermediate <- newroot <- oldroot
664 // but it will fail since newroot is self-signed.
665 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.paths[1]->error);
666 ASSERT_EQ(4U, result.paths[1]->path.size());
667 EXPECT_EQ(target_, result.paths[1]->path[0]);
668 EXPECT_EQ(newintermediate_, result.paths[1]->path[1]);
669 EXPECT_EQ(newroot_, result.paths[1]->path[2]);
670 EXPECT_EQ(oldroot_, result.paths[1]->path[3]);
671
672 // Path builder will skip:
673 // target <- newintermediate <- newroot <- newrootrollover <- ...
674 // Since newroot and newrootrollover have the same Name+SAN+SPKI.
675
676 // Finally path builder will use:
677 // target <- newintermediate <- newrootrollover <- oldroot
678 EXPECT_EQ(2U, result.best_result_index);
679 EXPECT_EQ(OK, result.paths[2]->error);
680 ASSERT_EQ(4U, result.paths[2]->path.size());
681 EXPECT_EQ(target_, result.paths[2]->path[0]);
682 EXPECT_EQ(newintermediate_, result.paths[2]->path[1]);
683 EXPECT_EQ(newrootrollover_, result.paths[2]->path[2]);
684 EXPECT_EQ(oldroot_, result.paths[2]->path[3]);
685 }
686
687 // If the target cert is a trust root, that alone is a valid path.
688 TEST_F(PathBuilderKeyRolloverTest, TestEndEntityIsTrustRoot) {
689 // Trust newintermediate.
690 TrustStore trust_store;
691 trust_store.AddTrustedCertificate(newintermediate_);
692
693 CertPathBuilder::Result result;
694 // Newintermediate is also the target cert.
695 CertPathBuilder path_builder(newintermediate_, &trust_store,
696 &signature_policy_, time_, &result);
697
698 EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
699
700 EXPECT_EQ(OK, result.error());
701
702 ASSERT_EQ(1U, result.paths.size());
703 EXPECT_EQ(OK, result.paths[0]->error);
704 ASSERT_EQ(1U, result.paths[0]->path.size());
705 EXPECT_EQ(newintermediate_, result.paths[0]->path[0]);
706 }
707
708 // If target has same Name+SAN+SPKI as a necessary intermediate, test if a path
709 // can still be built.
710 // Since LoopChecker will prevent the intermediate from being included, this
711 // currently does NOT verify. This case shouldn't occur in the web PKI.
712 TEST_F(PathBuilderKeyRolloverTest,
713 TestEndEntityHasSameNameAndSpkiAsIntermediate) {
714 // Trust oldroot.
715 TrustStore trust_store;
716 trust_store.AddTrustedCertificate(oldroot_);
717
718 // New root rollover is provided synchronously.
719 CertIssuerSourceStatic sync_certs;
720 sync_certs.AddCert(newrootrollover_);
721
722 CertPathBuilder::Result result;
723 // Newroot is the target cert.
724 CertPathBuilder path_builder(newroot_, &trust_store, &signature_policy_,
725 time_, &result);
726 path_builder.AddCertIssuerSource(&sync_certs);
727
728 EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
729
730 // This could actually be OK, but CertPathBuilder does not build the
731 // newroot <- newrootrollover <- oldroot path.
732 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.error());
733 }
734
735 // If target has same Name+SAN+SPKI as the trust root, test that a (trivial)
736 // path can still be built.
737 TEST_F(PathBuilderKeyRolloverTest,
738 TestEndEntityHasSameNameAndSpkiAsTrustAnchor) {
739 // Trust newrootrollover.
740 TrustStore trust_store;
741 trust_store.AddTrustedCertificate(newrootrollover_);
742
743 CertPathBuilder::Result result;
744 // Newroot is the target cert.
745 CertPathBuilder path_builder(newroot_, &trust_store, &signature_policy_,
746 time_, &result);
747
748 EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
749
750 EXPECT_EQ(OK, result.error());
751
752 ASSERT_FALSE(result.paths.empty());
753 const CertPathBuilder::ResultPath* best_result =
754 result.paths[result.best_result_index].get();
755
756 // Newroot has same name+SPKI as newrootrollover, thus the path is valid and
757 // only contains newroot.
758 EXPECT_EQ(OK, best_result->error);
759 ASSERT_EQ(1U, best_result->path.size());
760 EXPECT_EQ(newroot_, best_result->path[0]);
761 }
762
763 // Test that PathBuilder will not try the same path twice if multiple
764 // CertIssuerSources provide the same certificate.
765 TEST_F(PathBuilderKeyRolloverTest, TestDuplicateIntermediates) {
766 // Create a separate copy of oldintermediate.
767 scoped_refptr<ParsedCertificate> oldintermediate_dupe(
768 ParsedCertificate::CreateFromCertificateCopy(
769 oldintermediate_->der_cert().AsStringPiece(), {}));
770
771 // Only newroot is a trusted root.
772 TrustStore trust_store;
773 trust_store.AddTrustedCertificate(newroot_);
774
775 // The oldintermediate is supplied synchronously by |sync_certs1| and
776 // another copy of oldintermediate is supplied synchronously by |sync_certs2|.
777 // The path target <- oldintermediate <- newroot should be built first,
778 // though it won't verify. It should not be attempted again even though
779 // oldintermediate was supplied twice.
780 CertIssuerSourceStatic sync_certs1;
781 sync_certs1.AddCert(oldintermediate_);
782 CertIssuerSourceStatic sync_certs2;
783 sync_certs2.AddCert(oldintermediate_dupe);
784
785 // The newintermediate is supplied asynchronously, so the path
786 // target <- newintermediate <- newroot should be tried second.
787 AsyncCertIssuerSourceStatic async_certs;
788 async_certs.AddCert(newintermediate_);
789
790 CertPathBuilder::Result result;
791 CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_,
792 &result);
793 path_builder.AddCertIssuerSource(&sync_certs1);
794 path_builder.AddCertIssuerSource(&sync_certs2);
795 path_builder.AddCertIssuerSource(&async_certs);
796
797 EXPECT_EQ(CompletionStatus::ASYNC, RunPathBuilder(&path_builder));
798
799 EXPECT_EQ(OK, result.error());
800 ASSERT_EQ(2U, result.paths.size());
801
802 // Path builder will first attempt: target <- oldintermediate <- newroot
803 // but it will fail since oldintermediate is signed by oldroot.
804 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.paths[0]->error);
805 ASSERT_EQ(3U, result.paths[0]->path.size());
806 EXPECT_EQ(target_, result.paths[0]->path[0]);
807 // Compare the DER instead of ParsedCertificate pointer, don't care which copy
808 // of oldintermediate was used in the path.
809 EXPECT_EQ(oldintermediate_->der_cert(), result.paths[0]->path[1]->der_cert());
810 EXPECT_EQ(newroot_, result.paths[0]->path[2]);
811
812 // Path builder will next attempt: target <- newintermediate <- newroot
813 // which will succeed.
814 EXPECT_EQ(1U, result.best_result_index);
815 EXPECT_EQ(OK, result.paths[1]->error);
816 ASSERT_EQ(3U, result.paths[1]->path.size());
817 EXPECT_EQ(target_, result.paths[1]->path[0]);
818 EXPECT_EQ(newintermediate_, result.paths[1]->path[1]);
819 EXPECT_EQ(newroot_, result.paths[1]->path[2]);
820 }
821
822 // Test that PathBuilder will not try the same path twice if the same cert is
823 // presented via a CertIssuerSources and a TrustAnchor.
824 TEST_F(PathBuilderKeyRolloverTest, TestDuplicateIntermediateAndRoot) {
825 // Create a separate copy of newroot.
826 scoped_refptr<ParsedCertificate> newroot_dupe(
827 ParsedCertificate::CreateFromCertificateCopy(
828 newroot_->der_cert().AsStringPiece(), {}));
829
830 // Only newroot is a trusted root.
831 TrustStore trust_store;
832 trust_store.AddTrustedCertificate(newroot_);
833
834 // The oldintermediate and newroot are supplied synchronously by |sync_certs|.
835 CertIssuerSourceStatic sync_certs;
836 sync_certs.AddCert(oldintermediate_);
837 sync_certs.AddCert(newroot_dupe);
838
839 CertPathBuilder::Result result;
840 CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_,
841 &result);
842 path_builder.AddCertIssuerSource(&sync_certs);
843
844 EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
845
846 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.error());
847 ASSERT_EQ(1U, result.paths.size());
848
849 // Path builder attempt: target <- oldintermediate <- newroot
850 // but it will fail since oldintermediate is signed by oldroot.
851 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.paths[0]->error);
852 ASSERT_EQ(3U, result.paths[0]->path.size());
853 EXPECT_EQ(target_, result.paths[0]->path[0]);
854 EXPECT_EQ(oldintermediate_, result.paths[0]->path[1]);
855 // Compare the DER instead of ParsedCertificate pointer, don't care which copy
856 // of newroot was used in the path.
857 EXPECT_EQ(newroot_->der_cert(), result.paths[0]->path[2]->der_cert());
858 }
859
860 class MockCertIssuerSourceRequest : public CertIssuerSource::Request {
861 public:
862 MOCK_METHOD1(GetNext, CompletionStatus(scoped_refptr<ParsedCertificate>*));
863 };
864
865 class MockCertIssuerSource : public CertIssuerSource {
866 public:
867 MOCK_METHOD2(SyncGetIssuersOf,
868 void(const ParsedCertificate*, ParsedCertificateList*));
869 MOCK_METHOD3(AsyncGetIssuersOf,
870 void(const ParsedCertificate*,
871 const IssuerCallback&,
872 std::unique_ptr<Request>*));
873 };
874
875 // Helper class to pass the Request to the PathBuilder when it calls
876 // AsyncGetIssuersOf. (GoogleMock has a ByMove helper, but it apparently can
877 // only be used with Return, not SetArgPointee.)
878 class CertIssuerSourceRequestMover {
879 public:
880 CertIssuerSourceRequestMover(std::unique_ptr<CertIssuerSource::Request> req)
881 : request_(std::move(req)) {}
882 void MoveIt(const ParsedCertificate* cert,
883 const CertIssuerSource::IssuerCallback& issuers_callback,
884 std::unique_ptr<CertIssuerSource::Request>* out_req) {
885 *out_req = std::move(request_);
886 }
887
888 private:
889 std::unique_ptr<CertIssuerSource::Request> request_;
890 };
891
892 // Test that a single CertIssuerSource returning multiple async batches of
893 // issuers is handled correctly. Due to the StrictMocks, it also tests that path
894 // builder does not request issuers of certs that it shouldn't.
895 TEST_F(PathBuilderKeyRolloverTest, TestMultipleAsyncCallbacksFromSingleSource) {
896 StrictMock<MockCertIssuerSource> cert_issuer_source;
897
898 // Only newroot is a trusted root.
899 TrustStore trust_store;
900 trust_store.AddTrustedCertificate(newroot_);
901
902 CertPathBuilder::Result result;
903 CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_,
904 &result);
905 path_builder.AddCertIssuerSource(&cert_issuer_source);
906
907 CertIssuerSource::IssuerCallback target_issuers_callback;
908 // Create the mock CertIssuerSource::Request...
909 std::unique_ptr<StrictMock<MockCertIssuerSourceRequest>>
910 target_issuers_req_owner(new StrictMock<MockCertIssuerSourceRequest>());
911 // Keep a raw pointer to the Request...
912 StrictMock<MockCertIssuerSourceRequest>* target_issuers_req =
913 target_issuers_req_owner.get();
914 // Setup helper class to pass ownership of the Request to the PathBuilder when
915 // it calls AsyncGetIssuersOf.
916 CertIssuerSourceRequestMover req_mover(std::move(target_issuers_req_owner));
917 {
918 ::testing::InSequence s;
919 EXPECT_CALL(cert_issuer_source, SyncGetIssuersOf(target_.get(), _));
920 EXPECT_CALL(cert_issuer_source, AsyncGetIssuersOf(target_.get(), _, _))
921 .WillOnce(
922 DoAll(SaveArg<1>(&target_issuers_callback),
923 Invoke(&req_mover, &CertIssuerSourceRequestMover::MoveIt)));
924 }
925
926 TestClosure callback;
927 CompletionStatus rv = path_builder.Run(callback.closure());
928 ASSERT_EQ(CompletionStatus::ASYNC, rv);
929
930 ASSERT_FALSE(target_issuers_callback.is_null());
931
932 ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
933
934 // First async batch: return oldintermediate_.
935 EXPECT_CALL(*target_issuers_req, GetNext(_))
936 .WillOnce(DoAll(SetArgPointee<0>(oldintermediate_),
937 Return(CompletionStatus::SYNC)))
938 .WillOnce(
939 DoAll(SetArgPointee<0>(nullptr), Return(CompletionStatus::ASYNC)));
940 {
941 ::testing::InSequence s;
942 // oldintermediate_ does not create a valid path, so both sync and async
943 // lookups are expected.
944 EXPECT_CALL(cert_issuer_source,
945 SyncGetIssuersOf(oldintermediate_.get(), _));
946 EXPECT_CALL(cert_issuer_source,
947 AsyncGetIssuersOf(oldintermediate_.get(), _, _));
948 }
949 target_issuers_callback.Run(target_issuers_req);
950 ::testing::Mock::VerifyAndClearExpectations(target_issuers_req);
951 ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
952
953 // Second async batch: return newintermediate_.
954 EXPECT_CALL(*target_issuers_req, GetNext(_))
955 .WillOnce(DoAll(SetArgPointee<0>(newintermediate_),
956 Return(CompletionStatus::SYNC)))
957 .WillOnce(
958 DoAll(SetArgPointee<0>(nullptr), Return(CompletionStatus::ASYNC)));
959 // newroot_ is in the trust store, so this path will be completed
960 // synchronously. AsyncGetIssuersOf will not be called on newintermediate_.
961 EXPECT_CALL(cert_issuer_source, SyncGetIssuersOf(newintermediate_.get(), _));
962 target_issuers_callback.Run(target_issuers_req);
963 // Note that VerifyAndClearExpectations(target_issuers_req) is not called
964 // here. PathBuilder could have destroyed it already, so just let the
965 // expectations get checked by the destructor.
966 ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
967
968 // Ensure pathbuilder finished and filled result.
969 callback.WaitForResult();
970
971 EXPECT_EQ(OK, result.error());
972 ASSERT_EQ(2U, result.paths.size());
973
974 // Path builder first attempts: target <- oldintermediate <- newroot
975 // but it will fail since oldintermediate is signed by oldroot.
976 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.paths[0]->error);
977 ASSERT_EQ(3U, result.paths[0]->path.size());
978 EXPECT_EQ(target_, result.paths[0]->path[0]);
979 EXPECT_EQ(oldintermediate_, result.paths[0]->path[1]);
980 EXPECT_EQ(newroot_, result.paths[0]->path[2]);
981
982 // After the second batch of async results, path builder will attempt:
983 // target <- newintermediate <- newroot which will succeed.
984 EXPECT_EQ(OK, result.paths[1]->error);
985 ASSERT_EQ(3U, result.paths[1]->path.size());
986 EXPECT_EQ(target_, result.paths[1]->path[0]);
987 EXPECT_EQ(newintermediate_, result.paths[1]->path[1]);
988 EXPECT_EQ(newroot_, result.paths[1]->path[2]);
989 }
990
991 // Test that PathBuilder will not try the same path twice if CertIssuerSources
992 // asynchronously provide the same certificate multiple times.
993 TEST_F(PathBuilderKeyRolloverTest, TestDuplicateAsyncIntermediates) {
994 StrictMock<MockCertIssuerSource> cert_issuer_source;
995
996 // Only newroot is a trusted root.
997 TrustStore trust_store;
998 trust_store.AddTrustedCertificate(newroot_);
999
1000 CertPathBuilder::Result result;
1001 CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_,
1002 &result);
1003 path_builder.AddCertIssuerSource(&cert_issuer_source);
1004
1005 CertIssuerSource::IssuerCallback target_issuers_callback;
1006 // Create the mock CertIssuerSource::Request...
1007 std::unique_ptr<StrictMock<MockCertIssuerSourceRequest>>
1008 target_issuers_req_owner(new StrictMock<MockCertIssuerSourceRequest>());
1009 // Keep a raw pointer to the Request...
1010 StrictMock<MockCertIssuerSourceRequest>* target_issuers_req =
1011 target_issuers_req_owner.get();
1012 // Setup helper class to pass ownership of the Request to the PathBuilder when
1013 // it calls AsyncGetIssuersOf.
1014 CertIssuerSourceRequestMover req_mover(std::move(target_issuers_req_owner));
1015 {
1016 ::testing::InSequence s;
1017 EXPECT_CALL(cert_issuer_source, SyncGetIssuersOf(target_.get(), _));
1018 EXPECT_CALL(cert_issuer_source, AsyncGetIssuersOf(target_.get(), _, _))
1019 .WillOnce(
1020 DoAll(SaveArg<1>(&target_issuers_callback),
1021 Invoke(&req_mover, &CertIssuerSourceRequestMover::MoveIt)));
1022 }
1023
1024 TestClosure callback;
1025 CompletionStatus rv = path_builder.Run(callback.closure());
1026 ASSERT_EQ(CompletionStatus::ASYNC, rv);
1027
1028 ASSERT_FALSE(target_issuers_callback.is_null());
1029
1030 ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
1031
1032 // First async batch: return oldintermediate_.
1033 EXPECT_CALL(*target_issuers_req, GetNext(_))
1034 .WillOnce(DoAll(SetArgPointee<0>(oldintermediate_),
1035 Return(CompletionStatus::SYNC)))
1036 .WillOnce(
1037 DoAll(SetArgPointee<0>(nullptr), Return(CompletionStatus::ASYNC)));
1038 {
1039 ::testing::InSequence s;
1040 // oldintermediate_ does not create a valid path, so both sync and async
1041 // lookups are expected.
1042 EXPECT_CALL(cert_issuer_source,
1043 SyncGetIssuersOf(oldintermediate_.get(), _));
1044 EXPECT_CALL(cert_issuer_source,
1045 AsyncGetIssuersOf(oldintermediate_.get(), _, _));
1046 }
1047 target_issuers_callback.Run(target_issuers_req);
1048 ::testing::Mock::VerifyAndClearExpectations(target_issuers_req);
1049 ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
1050
1051 // Second async batch: return a different copy of oldintermediate_ again.
1052 scoped_refptr<ParsedCertificate> oldintermediate_dupe(
1053 ParsedCertificate::CreateFromCertificateCopy(
1054 oldintermediate_->der_cert().AsStringPiece(), {}));
1055 EXPECT_CALL(*target_issuers_req, GetNext(_))
1056 .WillOnce(DoAll(SetArgPointee<0>(oldintermediate_dupe),
1057 Return(CompletionStatus::SYNC)))
1058 .WillOnce(
1059 DoAll(SetArgPointee<0>(nullptr), Return(CompletionStatus::ASYNC)));
1060 target_issuers_callback.Run(target_issuers_req);
1061 // oldintermediate was already processed above, it should not generate any
1062 // more requests.
1063 ::testing::Mock::VerifyAndClearExpectations(target_issuers_req);
1064 ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
1065
1066 // Third async batch: return newintermediate_.
1067 EXPECT_CALL(*target_issuers_req, GetNext(_))
1068 .WillOnce(DoAll(SetArgPointee<0>(newintermediate_),
1069 Return(CompletionStatus::SYNC)))
1070 .WillOnce(
1071 DoAll(SetArgPointee<0>(nullptr), Return(CompletionStatus::ASYNC)));
1072 // newroot_ is in the trust store, so this path will be completed
1073 // synchronously. AsyncGetIssuersOf will not be called on newintermediate_.
1074 EXPECT_CALL(cert_issuer_source, SyncGetIssuersOf(newintermediate_.get(), _));
1075 target_issuers_callback.Run(target_issuers_req);
1076 // Note that VerifyAndClearExpectations(target_issuers_req) is not called
1077 // here. PathBuilder could have destroyed it already, so just let the
1078 // expectations get checked by the destructor.
1079 ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
1080
1081 // Ensure pathbuilder finished and filled result.
1082 callback.WaitForResult();
1083
1084 EXPECT_EQ(OK, result.error());
1085 ASSERT_EQ(2U, result.paths.size());
1086
1087 // Path builder first attempts: target <- oldintermediate <- newroot
1088 // but it will fail since oldintermediate is signed by oldroot.
1089 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.paths[0]->error);
1090 ASSERT_EQ(3U, result.paths[0]->path.size());
1091 EXPECT_EQ(target_, result.paths[0]->path[0]);
1092 EXPECT_EQ(oldintermediate_, result.paths[0]->path[1]);
1093 EXPECT_EQ(newroot_, result.paths[0]->path[2]);
1094
1095 // The second async result does not generate any path.
1096
1097 // After the third batch of async results, path builder will attempt:
1098 // target <- newintermediate <- newroot which will succeed.
1099 EXPECT_EQ(OK, result.paths[1]->error);
1100 ASSERT_EQ(3U, result.paths[1]->path.size());
1101 EXPECT_EQ(target_, result.paths[1]->path[0]);
1102 EXPECT_EQ(newintermediate_, result.paths[1]->path[1]);
1103 EXPECT_EQ(newroot_, result.paths[1]->path[2]);
1104 }
1105
1106 } // namespace
1107
1108 } // namespace net
OLDNEW
« no previous file with comments | « net/cert/internal/path_builder_pkits_unittest.cc ('k') | net/cert/internal/path_builder_verify_certificate_chain_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698