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

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 comment #16 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)
eroman 2016/07/01 23:49:29 side-comment: Seems legit, although not sure if st
mattm 2016/07/02 02:21:51 seems to be: https://chromium-cpp.appspot.com/ (R
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,
eroman 2016/07/01 23:49:29 Should we randomize the order of the intermediates
mattm 2016/07/02 02:21:51 Probably not actual randomization (since even if i
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(a_by_b_);
eroman 2016/07/01 23:49:29 Does this have an effect on path building, or just
mattm 2016/07/02 02:21:51 No effect. I don't remember if that was on purpose
270 sync_certs.AddCert(b_by_f_);
271 sync_certs.AddCert(f_by_e_);
272
273 AsyncCertIssuerSourceStatic async_certs;
274 async_certs.AddCert(b_by_c_);
eroman 2016/07/01 23:49:29 What would happen if b_by_c were returned synchron
mattm 2016/07/02 02:21:51 Yes.
275 async_certs.AddCert(c_by_e_);
276
277 CertPathBuilder::Result result;
278 CertPathBuilder path_builder(a_by_b_, &trust_store, &signature_policy_, time_,
279 &result);
280 path_builder.AddCertIssuerSource(&async_certs);
281 path_builder.AddCertIssuerSource(&sync_certs);
282
283 EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
284
285 EXPECT_EQ(OK, result.error());
286 EXPECT_EQ(0, async_certs.num_async_gets());
287 }
288
289 // Test that async cert queries are not made if no callback is provided.
290 TEST_F(PathBuilderMultiRootTest, SychronousOnlyMode) {
291 TrustStore trust_store;
292 trust_store.AddTrustedCertificate(e_by_e_);
293
294 CertIssuerSourceStatic sync_certs;
295 sync_certs.AddCert(f_by_e_);
296
297 AsyncCertIssuerSourceStatic async_certs;
298 async_certs.AddCert(b_by_f_);
299
300 CertPathBuilder::Result result;
301 CertPathBuilder path_builder(a_by_b_, &trust_store, &signature_policy_, time_,
302 &result);
303 path_builder.AddCertIssuerSource(&async_certs);
304 path_builder.AddCertIssuerSource(&sync_certs);
305
306 EXPECT_EQ(CompletionStatus::SYNC, path_builder.Run(base::Closure()));
307
308 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.error());
309 EXPECT_EQ(0, async_certs.num_async_gets());
310 }
311
312 // If async queries are needed, all async sources will be queried
313 // simultaneously.
314 TEST_F(PathBuilderMultiRootTest, TestAsyncSimultaneous) {
315 TrustStore trust_store;
316 trust_store.AddTrustedCertificate(e_by_e_);
317
318 CertIssuerSourceStatic sync_certs;
319 sync_certs.AddCert(a_by_b_);
320 sync_certs.AddCert(b_by_c_);
321 sync_certs.AddCert(b_by_f_);
322
323 AsyncCertIssuerSourceStatic async_certs1;
324 async_certs1.AddCert(c_by_e_);
325
326 AsyncCertIssuerSourceStatic async_certs2;
327 async_certs2.AddCert(f_by_e_);
328
329 CertPathBuilder::Result result;
330 CertPathBuilder path_builder(a_by_b_, &trust_store, &signature_policy_, time_,
331 &result);
332 path_builder.AddCertIssuerSource(&async_certs1);
333 path_builder.AddCertIssuerSource(&async_certs2);
334 path_builder.AddCertIssuerSource(&sync_certs);
335
336 EXPECT_EQ(CompletionStatus::ASYNC, RunPathBuilder(&path_builder));
337
338 EXPECT_EQ(OK, result.error());
339 EXPECT_EQ(1, async_certs1.num_async_gets());
340 EXPECT_EQ(1, async_certs2.num_async_gets());
341 }
342
343 // Test that PathBuilder does not generate longer paths than necessary if one of
344 // the supplied certs is itself a trust anchor.
345 TEST_F(PathBuilderMultiRootTest, TestLongChain) {
346 // Both D(D) and C(D) are trusted roots.
347 TrustStore trust_store;
348 trust_store.AddTrustedCertificate(d_by_d_);
349 trust_store.AddTrustedCertificate(c_by_d_);
350
351 // Certs A(B), B(C), and C(D) are all supplied.
352 CertIssuerSourceStatic sync_certs;
353 sync_certs.AddCert(a_by_b_);
354 sync_certs.AddCert(b_by_c_);
355 sync_certs.AddCert(c_by_d_);
356
357 CertPathBuilder::Result result;
358 CertPathBuilder path_builder(a_by_b_, &trust_store, &signature_policy_, time_,
359 &result);
360 path_builder.AddCertIssuerSource(&sync_certs);
361
362 EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
363
364 EXPECT_EQ(OK, result.error());
365
366 // The result path should be A(B) <- B(C) <- C(D)
367 // not the longer but also valid A(B) <- B(C) <- C(D) <- D(D)
368 EXPECT_EQ(3U, result.paths[result.best_result_index]->path.size());
369 }
370
371 // Test that PathBuilder will backtrack and try a different path if the first
372 // one doesn't work out.
373 TEST_F(PathBuilderMultiRootTest, TestBacktracking) {
374 // Only D(D) is a trusted root.
375 TrustStore trust_store;
376 trust_store.AddTrustedCertificate(d_by_d_);
377
378 // Certs A(B), B(F), and F(E) are supplied synchronously, thus the path
379 // A(B) <- B(F) <- F(E) should be built first, though it won't verify.
380 CertIssuerSourceStatic sync_certs;
381 sync_certs.AddCert(a_by_b_);
382 sync_certs.AddCert(b_by_f_);
383 sync_certs.AddCert(f_by_e_);
384
385 // Certs B(C), and C(D) are supplied asynchronously, so the path
386 // A(B) <- B(C) <- C(D) <- D(D) should be tried second.
387 AsyncCertIssuerSourceStatic async_certs;
388 async_certs.AddCert(b_by_c_);
389 async_certs.AddCert(c_by_d_);
390
391 CertPathBuilder::Result result;
392 CertPathBuilder path_builder(a_by_b_, &trust_store, &signature_policy_, time_,
393 &result);
394 path_builder.AddCertIssuerSource(&sync_certs);
395 path_builder.AddCertIssuerSource(&async_certs);
396
397 EXPECT_EQ(CompletionStatus::ASYNC, RunPathBuilder(&path_builder));
398
399 EXPECT_EQ(OK, result.error());
400
401 // The result path should be A(B) <- B(C) <- C(D) <- D(D)
402 ASSERT_EQ(4U, result.paths[result.best_result_index]->path.size());
403 EXPECT_EQ(a_by_b_, result.paths[result.best_result_index]->path[0]);
404 EXPECT_EQ(b_by_c_, result.paths[result.best_result_index]->path[1]);
405 EXPECT_EQ(c_by_d_, result.paths[result.best_result_index]->path[2]);
406 EXPECT_EQ(d_by_d_, result.paths[result.best_result_index]->path[3]);
407 }
408
409 class PathBuilderKeyRolloverTest : public ::testing::Test {
410 public:
411 PathBuilderKeyRolloverTest() : signature_policy_(1024) {}
412
413 void SetUp() override {
414 std::vector<std::string> path;
415
416 ReadVerifyCertChainTestFromFile(
417 "net/data/verify_certificate_chain_unittest/key-rollover-oldchain.pem",
418 &path, &oldroot_, &time_);
419 ASSERT_EQ(2U, path.size());
420 target_ = ParsedCertificate::CreateFromCertificateCopy(path[0], {});
421 oldintermediary_ =
422 ParsedCertificate::CreateFromCertificateCopy(path[1], {});
423 ASSERT_TRUE(target_);
424 ASSERT_TRUE(oldintermediary_);
425
426 ReadVerifyCertChainTestFromFile(
427 "net/data/verify_certificate_chain_unittest/"
428 "key-rollover-longrolloverchain.pem",
429 &path, &oldroot_, &time_);
430 ASSERT_EQ(4U, path.size());
431 newintermediary_ =
432 ParsedCertificate::CreateFromCertificateCopy(path[1], {});
433 newroot_ = ParsedCertificate::CreateFromCertificateCopy(path[2], {});
434 newrootrollover_ =
435 ParsedCertificate::CreateFromCertificateCopy(path[3], {});
436 ASSERT_TRUE(newintermediary_);
437 ASSERT_TRUE(newroot_);
438 ASSERT_TRUE(newrootrollover_);
439 }
440
441 protected:
442 // oldroot-------->newrootrollover newroot
443 // | | |
444 // v v v
445 // oldintermediary newintermediary
446 // | |
447 // +------------+-------------+
448 // |
449 // v
450 // target
451 scoped_refptr<ParsedCertificate> target_, oldintermediary_, newintermediary_,
eroman 2016/07/01 23:49:29 nit: one per line
mattm 2016/07/02 02:21:51 Done.
452 oldroot_, newroot_, newrootrollover_;
453
454 SimpleSignaturePolicy signature_policy_;
455 der::GeneralizedTime time_;
456 };
457
458 // Tests that if only the old root cert is trusted, the path builder can build a
459 // path through the new intermediate and rollover cert to the old root.
460 TEST_F(PathBuilderKeyRolloverTest, TestRolloverOnlyOldRootTrusted) {
461 // Only oldroot is trusted.
462 TrustStore trust_store;
463 trust_store.AddTrustedCertificate(oldroot_);
464
465 // Old intermediary cert is not provided, so the pathbuilder will need to go
eroman 2016/07/01 23:49:29 Not sure if one is more correct than another, but
mattm 2016/07/02 02:21:51 Done.
466 // through the rollover cert.
467 CertIssuerSourceStatic sync_certs;
468 sync_certs.AddCert(newintermediary_);
469 sync_certs.AddCert(newrootrollover_);
470
471 CertPathBuilder::Result result;
472 CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_,
473 &result);
474 path_builder.AddCertIssuerSource(&sync_certs);
475
476 EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
477
478 EXPECT_EQ(OK, result.error());
479
480 // Path builder will first attempt: target <- newintermediary <- oldroot
481 // but it will fail since newintermediary is signed by newroot.
482 ASSERT_EQ(2U, result.paths.size());
483 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.paths[0]->error);
484 ASSERT_EQ(3U, result.paths[0]->path.size());
485 EXPECT_EQ(target_, result.paths[0]->path[0]);
486 EXPECT_EQ(newintermediary_, result.paths[0]->path[1]);
487 EXPECT_EQ(oldroot_, result.paths[0]->path[2]);
488
489 // Path builder will next attempt:
490 // target <- newintermediary <- newrootrollover <- oldroot
491 // which will succeed.
492 EXPECT_EQ(1U, result.best_result_index);
493 EXPECT_EQ(OK, result.paths[1]->error);
494 ASSERT_EQ(4U, result.paths[1]->path.size());
495 EXPECT_EQ(target_, result.paths[1]->path[0]);
496 EXPECT_EQ(newintermediary_, result.paths[1]->path[1]);
497 EXPECT_EQ(newrootrollover_, result.paths[1]->path[2]);
498 EXPECT_EQ(oldroot_, result.paths[1]->path[3]);
499 }
500
501 // Tests that if both old and new roots are trusted it can build a path through
502 // either.
503 // TODO(mattm): Once prioritization is implemented, it should test that it
504 // always builds the path through the new intermediary and new root.
505 TEST_F(PathBuilderKeyRolloverTest, TestRolloverBothRootsTrusted) {
506 // Both oldroot and newroot are trusted.
507 TrustStore trust_store;
508 trust_store.AddTrustedCertificate(oldroot_);
509 trust_store.AddTrustedCertificate(newroot_);
510
511 // Both old and new intermediates + rollover cert are provided.
512 CertIssuerSourceStatic sync_certs;
513 sync_certs.AddCert(oldintermediary_);
514 sync_certs.AddCert(newintermediary_);
515 sync_certs.AddCert(newrootrollover_);
516
517 CertPathBuilder::Result result;
518 CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_,
519 &result);
520 path_builder.AddCertIssuerSource(&sync_certs);
521
522 EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
523
524 EXPECT_EQ(OK, result.error());
525
526 // Path builder willattempt one of:
527 // target <- oldintermediary <- oldroot
528 // target <- newintermediary <- newroot
529 // either will succeed.
530 ASSERT_EQ(1U, result.paths.size());
531 EXPECT_EQ(OK, result.paths[0]->error);
532 ASSERT_EQ(3U, result.paths[0]->path.size());
533 EXPECT_EQ(target_, result.paths[0]->path[0]);
534 if (result.paths[0]->path[1] != newintermediary_) {
535 DVLOG(1) << "USED OLD";
536 EXPECT_EQ(oldintermediary_, result.paths[0]->path[1]);
537 EXPECT_EQ(oldroot_, result.paths[0]->path[2]);
538 } else {
539 DVLOG(1) << "USED NEW";
540 EXPECT_EQ(newintermediary_, result.paths[0]->path[1]);
541 EXPECT_EQ(newroot_, result.paths[0]->path[2]);
542 }
543 }
544
545 // Tests that multiple trust root matches on a single path will be considered.
546 // Both roots have the same subject but different keys. Only one of them will
547 // verify.
548 TEST_F(PathBuilderKeyRolloverTest, TestMultipleRootMatchesOnlyOneWorks) {
549 // Both newroot and oldroot are trusted.
550 TrustStore trust_store;
551 // Note: The test assumes newroot will be tried before oldroot.
552 // Currently this depends on the order the roots are added.
553 trust_store.AddTrustedCertificate(newroot_);
554 trust_store.AddTrustedCertificate(oldroot_);
555
556 // Only oldintermediary is supplied, so the path with newroot should fail,
557 // oldroot should succeed.
558 CertIssuerSourceStatic sync_certs;
559 sync_certs.AddCert(oldintermediary_);
560
561 CertPathBuilder::Result result;
562 CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_,
563 &result);
564 path_builder.AddCertIssuerSource(&sync_certs);
565
566 EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
567
568 EXPECT_EQ(OK, result.error());
569 ASSERT_EQ(2U, result.paths.size());
570
571 // Path builder will first attempt: target <- oldintermediary <- newroot
572 // but it will fail since oldintermediary is signed by oldroot.
573 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.paths[0]->error);
574 ASSERT_EQ(3U, result.paths[0]->path.size());
575 EXPECT_EQ(target_, result.paths[0]->path[0]);
576 EXPECT_EQ(oldintermediary_, result.paths[0]->path[1]);
577 EXPECT_EQ(newroot_, result.paths[0]->path[2]);
578
579 // Path builder will next attempt:
580 // target <- old intermediary <- oldroot
581 // which should succeed.
582 EXPECT_EQ(OK, result.paths[1]->error);
583 ASSERT_EQ(3U, result.paths[1]->path.size());
584 EXPECT_EQ(target_, result.paths[1]->path[0]);
585 EXPECT_EQ(oldintermediary_, result.paths[1]->path[1]);
586 EXPECT_EQ(oldroot_, result.paths[1]->path[2]);
587 }
588
589 // Tests that the path builder doesn't build longer than necessary paths.
590 TEST_F(PathBuilderKeyRolloverTest, TestRolloverLongChain) {
591 // Only oldroot is trusted.
592 TrustStore trust_store;
593 trust_store.AddTrustedCertificate(oldroot_);
594
595 // New intermediate and new root are provided synchronously.
596 CertIssuerSourceStatic sync_certs;
597 sync_certs.AddCert(newintermediary_);
598 sync_certs.AddCert(newroot_);
599
600 // Rollover cert is only provided asynchronously. This will force the
601 // pathbuilder to first try building a longer than necessary path.
602 AsyncCertIssuerSourceStatic async_certs;
603 async_certs.AddCert(newrootrollover_);
604
605 CertPathBuilder::Result result;
606 CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_,
607 &result);
608 path_builder.AddCertIssuerSource(&sync_certs);
609 path_builder.AddCertIssuerSource(&async_certs);
610
611 EXPECT_EQ(CompletionStatus::ASYNC, RunPathBuilder(&path_builder));
612
613 EXPECT_EQ(OK, result.error());
614 ASSERT_EQ(3U, result.paths.size());
615
616 // Path builder will first attempt: target <- newintermediary <- oldroot
617 // but it will fail since newintermediary is signed by newroot.
618 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.paths[0]->error);
619 ASSERT_EQ(3U, result.paths[0]->path.size());
620 EXPECT_EQ(target_, result.paths[0]->path[0]);
621 EXPECT_EQ(newintermediary_, result.paths[0]->path[1]);
622 EXPECT_EQ(oldroot_, result.paths[0]->path[2]);
623
624 // Path builder will next attempt:
625 // target <- newintermediary <- newroot <- oldroot
626 // but it will fail since newroot is self-signed.
627 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.paths[1]->error);
628 ASSERT_EQ(4U, result.paths[1]->path.size());
629 EXPECT_EQ(target_, result.paths[1]->path[0]);
630 EXPECT_EQ(newintermediary_, result.paths[1]->path[1]);
631 EXPECT_EQ(newroot_, result.paths[1]->path[2]);
632 EXPECT_EQ(oldroot_, result.paths[1]->path[3]);
633
634 // Path builder will skip:
635 // target <- newintermediary <- newroot <- newrootrollover <- ...
636 // Since newroot and newrootrollover have the same Name+SAN+SPKI.
637
638 // Finally path builder will use:
639 // target <- newintermediary <- newrootrollover <- oldroot
640 EXPECT_EQ(2U, result.best_result_index);
641 EXPECT_EQ(OK, result.paths[2]->error);
642 ASSERT_EQ(4U, result.paths[2]->path.size());
643 EXPECT_EQ(target_, result.paths[2]->path[0]);
644 EXPECT_EQ(newintermediary_, result.paths[2]->path[1]);
645 EXPECT_EQ(newrootrollover_, result.paths[2]->path[2]);
646 EXPECT_EQ(oldroot_, result.paths[2]->path[3]);
647 }
648
649 // If the target cert is a trust root, that alone is a valid path.
650 TEST_F(PathBuilderKeyRolloverTest, TestEndEntityIsTrustRoot) {
651 // Trust newintermediary.
652 TrustStore trust_store;
653 trust_store.AddTrustedCertificate(newintermediary_);
654
655 CertPathBuilder::Result result;
656 // Newintermediary is also the target cert.
657 CertPathBuilder path_builder(newintermediary_, &trust_store,
658 &signature_policy_, time_, &result);
659
660 EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
661
662 EXPECT_EQ(OK, result.error());
663
664 ASSERT_EQ(1U, result.paths.size());
665 EXPECT_EQ(OK, result.paths[0]->error);
666 ASSERT_EQ(1U, result.paths[0]->path.size());
667 EXPECT_EQ(newintermediary_, result.paths[0]->path[0]);
668 }
669
670 // If target has same Name+SAN+SPKI as a necessary intermediate, test if a path
671 // can still be built.
672 // Since LoopChecker will prevent the intermediate from being included, this
673 // currently does NOT verify. This case shouldn't occur in the web PKI.
674 TEST_F(PathBuilderKeyRolloverTest,
675 TestEndEntityHasSameNameAndSpkiAsIntermediate) {
676 // Trust oldroot.
677 TrustStore trust_store;
678 trust_store.AddTrustedCertificate(oldroot_);
679
680 // New root rollover is provided synchronously.
681 CertIssuerSourceStatic sync_certs;
682 sync_certs.AddCert(newrootrollover_);
683
684 CertPathBuilder::Result result;
685 // Newroot is the target cert.
686 CertPathBuilder path_builder(newroot_, &trust_store, &signature_policy_,
687 time_, &result);
688 path_builder.AddCertIssuerSource(&sync_certs);
689
690 EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
691
692 // This could actually be OK, but CertPathBuilder does not build the
693 // newroot <- newrootrollover <- oldroot path.
694 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.error());
695 }
696
697 // If target has same Name+SAN+SPKI as the trust root, test that a (trivial)
698 // path can still be built.
699 TEST_F(PathBuilderKeyRolloverTest,
700 TestEndEntityHasSameNameAndSpkiAsTrustAnchor) {
701 // Trust newrootrollover.
702 TrustStore trust_store;
703 trust_store.AddTrustedCertificate(newrootrollover_);
704
705 CertPathBuilder::Result result;
706 // Newroot is the target cert.
707 CertPathBuilder path_builder(newroot_, &trust_store, &signature_policy_,
708 time_, &result);
709
710 EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
711
712 EXPECT_EQ(OK, result.error());
713
714 ASSERT_FALSE(result.paths.empty());
715 const CertPathBuilder::ResultPath* best_result =
716 result.paths[result.best_result_index].get();
717
718 // Newroot has same name+SPKI as newrootrollover, thus the path is valid and
719 // only contains newroot.
720 EXPECT_EQ(OK, best_result->error);
721 ASSERT_EQ(1U, best_result->path.size());
722 EXPECT_EQ(newroot_, best_result->path[0]);
723 }
724
725 // Test that PathBuilder will not try the same path twice if multiple
726 // CertIssuerSources provide the same certificate.
727 TEST_F(PathBuilderKeyRolloverTest, TestDuplicateIntermediates) {
728 // Create a separate copy of oldintermediary.
729 scoped_refptr<ParsedCertificate> oldintermediary_dupe(
730 ParsedCertificate::CreateFromCertificateCopy(
731 oldintermediary_->der_cert().AsStringPiece(), {}));
732
733 // Only newroot is a trusted root.
734 TrustStore trust_store;
735 trust_store.AddTrustedCertificate(newroot_);
736
737 // The oldintermediary is supplied synchronously by |sync_certs1| and
738 // another copy of oldintermediary is supplied synchronously by |sync_certs2|.
739 // The path target <- oldintermediary <- newroot should be built first,
740 // though it won't verify. It should not be attempted again even though
741 // oldintermediary was supplied twice.
742 CertIssuerSourceStatic sync_certs1;
743 sync_certs1.AddCert(oldintermediary_);
744 CertIssuerSourceStatic sync_certs2;
745 sync_certs2.AddCert(oldintermediary_dupe);
746
747 // The newintermediary is supplied asynchronously, so the path
748 // target <- newintermediary <- newroot should be tried second.
749 AsyncCertIssuerSourceStatic async_certs;
750 async_certs.AddCert(newintermediary_);
751
752 CertPathBuilder::Result result;
753 CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_,
754 &result);
755 path_builder.AddCertIssuerSource(&sync_certs1);
756 path_builder.AddCertIssuerSource(&sync_certs2);
757 path_builder.AddCertIssuerSource(&async_certs);
758
759 EXPECT_EQ(CompletionStatus::ASYNC, RunPathBuilder(&path_builder));
760
761 EXPECT_EQ(OK, result.error());
762 ASSERT_EQ(2U, result.paths.size());
763
764 // Path builder will first attempt: target <- oldintermediary <- newroot
765 // but it will fail since oldintermediary is signed by oldroot.
766 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.paths[0]->error);
767 ASSERT_EQ(3U, result.paths[0]->path.size());
768 EXPECT_EQ(target_, result.paths[0]->path[0]);
769 // Compare the DER instead of ParsedCertificate pointer, don't care which copy
770 // of oldintermediary was used in the path.
771 EXPECT_EQ(oldintermediary_->der_cert(), result.paths[0]->path[1]->der_cert());
772 EXPECT_EQ(newroot_, result.paths[0]->path[2]);
773
774 // Path builder will next attempt: target <- newintermediary <- newroot
775 // which will succeed.
776 EXPECT_EQ(1U, result.best_result_index);
777 EXPECT_EQ(OK, result.paths[1]->error);
778 ASSERT_EQ(3U, result.paths[1]->path.size());
779 EXPECT_EQ(target_, result.paths[1]->path[0]);
780 EXPECT_EQ(newintermediary_, result.paths[1]->path[1]);
781 EXPECT_EQ(newroot_, result.paths[1]->path[2]);
782 }
783
784 // Test that PathBuilder will not try the same path twice if the same cert is
785 // presented via a CertIssuerSources and a TrustAnchor.
786 TEST_F(PathBuilderKeyRolloverTest, TestDuplicateIntermediateAndRoot) {
787 // Create a separate copy of newroot.
788 scoped_refptr<ParsedCertificate> newroot_dupe(
789 ParsedCertificate::CreateFromCertificateCopy(
790 newroot_->der_cert().AsStringPiece(), {}));
791
792 // Only newroot is a trusted root.
793 TrustStore trust_store;
794 trust_store.AddTrustedCertificate(newroot_);
795
796 // The oldintermediary and newroot are supplied synchronously by |sync_certs|.
797 CertIssuerSourceStatic sync_certs;
798 sync_certs.AddCert(oldintermediary_);
799 sync_certs.AddCert(newroot_dupe);
800
801 CertPathBuilder::Result result;
802 CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_,
803 &result);
804 path_builder.AddCertIssuerSource(&sync_certs);
805
806 EXPECT_EQ(CompletionStatus::SYNC, RunPathBuilder(&path_builder));
807
808 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.error());
809 ASSERT_EQ(1U, result.paths.size());
810
811 // Path builder attempt: target <- oldintermediary <- newroot
812 // but it will fail since oldintermediary is signed by oldroot.
813 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.paths[0]->error);
814 ASSERT_EQ(3U, result.paths[0]->path.size());
815 EXPECT_EQ(target_, result.paths[0]->path[0]);
816 EXPECT_EQ(oldintermediary_, result.paths[0]->path[1]);
817 // Compare the DER instead of ParsedCertificate pointer, don't care which copy
818 // of newroot was used in the path.
819 EXPECT_EQ(newroot_->der_cert(), result.paths[0]->path[2]->der_cert());
820 }
821
822 class MockCertIssuerSourceRequest : public CertIssuerSource::Request {
823 public:
824 MOCK_METHOD1(GetNext, CompletionStatus(scoped_refptr<ParsedCertificate>*));
825 };
826
827 class MockCertIssuerSource : public CertIssuerSource {
828 public:
829 MOCK_METHOD2(SyncGetIssuersOf,
830 void(const ParsedCertificate*, ParsedCertificateList*));
831 MOCK_METHOD3(AsyncGetIssuersOf,
832 void(const ParsedCertificate*,
833 const IssuerCallback&,
834 std::unique_ptr<Request>*));
835 };
836
837 // Helper class to pass the Request to the PathBuilder when it calls
838 // AsyncGetIssuersOf. (GoogleMock has a ByMove helper, but it apparently can
839 // only be used with Return, not SetArgPointee.)
840 class CertIssuerSourceRequestMover {
841 public:
842 CertIssuerSourceRequestMover(std::unique_ptr<CertIssuerSource::Request> req)
843 : request_(std::move(req)) {}
844 void MoveIt(const ParsedCertificate* cert,
845 const CertIssuerSource::IssuerCallback& issuers_callback,
846 std::unique_ptr<CertIssuerSource::Request>* out_req) {
847 *out_req = std::move(request_);
848 }
849
850 private:
851 std::unique_ptr<CertIssuerSource::Request> request_;
852 };
853
854 // Test that a single CertIssuerSource returning multiple async batches of
855 // issuers is handled correctly. Due to the StrictMocks, it also tests that path
856 // builder does not request issuers of certs that it shouldn't.
857 TEST_F(PathBuilderKeyRolloverTest, TestMultipleAsyncCallbacksFromSingleSource) {
858 StrictMock<MockCertIssuerSource> cert_issuer_source;
859
860 // Only newroot is a trusted root.
861 TrustStore trust_store;
862 trust_store.AddTrustedCertificate(newroot_);
863
864 CertPathBuilder::Result result;
865 CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_,
866 &result);
867 path_builder.AddCertIssuerSource(&cert_issuer_source);
868
869 CertIssuerSource::IssuerCallback target_issuers_callback;
870 // Create the mock CertIssuerSource::Request...
871 std::unique_ptr<StrictMock<MockCertIssuerSourceRequest>>
872 target_issuers_req_owner(new StrictMock<MockCertIssuerSourceRequest>());
873 // Keep a raw pointer to the Request...
874 StrictMock<MockCertIssuerSourceRequest>* target_issuers_req =
875 target_issuers_req_owner.get();
876 // Setup helper class to pass ownership of the Request to the PathBuilder when
877 // it calls AsyncGetIssuersOf.
878 CertIssuerSourceRequestMover req_mover(std::move(target_issuers_req_owner));
879 {
880 ::testing::InSequence s;
881 EXPECT_CALL(cert_issuer_source, SyncGetIssuersOf(target_.get(), _));
882 EXPECT_CALL(cert_issuer_source, AsyncGetIssuersOf(target_.get(), _, _))
883 .WillOnce(
884 DoAll(SaveArg<1>(&target_issuers_callback),
885 Invoke(&req_mover, &CertIssuerSourceRequestMover::MoveIt)));
886 }
887
888 TestClosure callback;
889 CompletionStatus rv = path_builder.Run(callback.closure());
890 ASSERT_EQ(CompletionStatus::ASYNC, rv);
891
892 ASSERT_FALSE(target_issuers_callback.is_null());
893
894 ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
895
896 // First async batch: return oldintermediary_.
897 EXPECT_CALL(*target_issuers_req, GetNext(_))
898 .WillOnce(DoAll(SetArgPointee<0>(oldintermediary_),
899 Return(CompletionStatus::SYNC)))
900 .WillOnce(
901 DoAll(SetArgPointee<0>(nullptr), Return(CompletionStatus::ASYNC)));
902 {
903 ::testing::InSequence s;
904 // oldintermediary_ does not create a valid path, so both sync and async
905 // lookups are expected.
906 EXPECT_CALL(cert_issuer_source,
907 SyncGetIssuersOf(oldintermediary_.get(), _));
908 EXPECT_CALL(cert_issuer_source,
909 AsyncGetIssuersOf(oldintermediary_.get(), _, _));
910 }
911 target_issuers_callback.Run(target_issuers_req);
912 ::testing::Mock::VerifyAndClearExpectations(target_issuers_req);
913 ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
914
915 // Second async batch: return newintermediary_.
916 EXPECT_CALL(*target_issuers_req, GetNext(_))
917 .WillOnce(DoAll(SetArgPointee<0>(newintermediary_),
918 Return(CompletionStatus::SYNC)))
919 .WillOnce(
920 DoAll(SetArgPointee<0>(nullptr), Return(CompletionStatus::ASYNC)));
921 // newroot_ is in the trust store, so this path will be completed
922 // synchronously. AsyncGetIssuersOf will not be called on newintermediary_.
923 EXPECT_CALL(cert_issuer_source, SyncGetIssuersOf(newintermediary_.get(), _));
924 target_issuers_callback.Run(target_issuers_req);
925 // Note that VerifyAndClearExpectations(target_issuers_req) is not called
926 // here. PathBuilder could have destroyed it already, so just let the
927 // expectations get checked by the destructor.
928 ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
929
930 // Ensure pathbuilder finished and filled result.
931 callback.WaitForResult();
932
933 EXPECT_EQ(OK, result.error());
934 ASSERT_EQ(2U, result.paths.size());
935
936 // Path builder first attempts: target <- oldintermediary <- newroot
937 // but it will fail since oldintermediary is signed by oldroot.
938 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.paths[0]->error);
939 ASSERT_EQ(3U, result.paths[0]->path.size());
940 EXPECT_EQ(target_, result.paths[0]->path[0]);
941 EXPECT_EQ(oldintermediary_, result.paths[0]->path[1]);
942 EXPECT_EQ(newroot_, result.paths[0]->path[2]);
943
944 // After the second batch of async results, path builder will attempt:
945 // target <- newintermediary <- newroot which will succeed.
946 EXPECT_EQ(OK, result.paths[1]->error);
947 ASSERT_EQ(3U, result.paths[1]->path.size());
948 EXPECT_EQ(target_, result.paths[1]->path[0]);
949 EXPECT_EQ(newintermediary_, result.paths[1]->path[1]);
950 EXPECT_EQ(newroot_, result.paths[1]->path[2]);
951 }
952
953 // Test that PathBuilder will not try the same path twice if CertIssuerSources
954 // asynchronously provide the same certificate multiple times.
955 TEST_F(PathBuilderKeyRolloverTest, TestDuplicateAsyncIntermediates) {
956 StrictMock<MockCertIssuerSource> cert_issuer_source;
957
958 // Only newroot is a trusted root.
959 TrustStore trust_store;
960 trust_store.AddTrustedCertificate(newroot_);
961
962 CertPathBuilder::Result result;
963 CertPathBuilder path_builder(target_, &trust_store, &signature_policy_, time_,
964 &result);
965 path_builder.AddCertIssuerSource(&cert_issuer_source);
966
967 CertIssuerSource::IssuerCallback target_issuers_callback;
968 // Create the mock CertIssuerSource::Request...
969 std::unique_ptr<StrictMock<MockCertIssuerSourceRequest>>
970 target_issuers_req_owner(new StrictMock<MockCertIssuerSourceRequest>());
971 // Keep a raw pointer to the Request...
972 StrictMock<MockCertIssuerSourceRequest>* target_issuers_req =
973 target_issuers_req_owner.get();
974 // Setup helper class to pass ownership of the Request to the PathBuilder when
975 // it calls AsyncGetIssuersOf.
976 CertIssuerSourceRequestMover req_mover(std::move(target_issuers_req_owner));
977 {
978 ::testing::InSequence s;
979 EXPECT_CALL(cert_issuer_source, SyncGetIssuersOf(target_.get(), _));
980 EXPECT_CALL(cert_issuer_source, AsyncGetIssuersOf(target_.get(), _, _))
981 .WillOnce(
982 DoAll(SaveArg<1>(&target_issuers_callback),
983 Invoke(&req_mover, &CertIssuerSourceRequestMover::MoveIt)));
984 }
985
986 TestClosure callback;
987 CompletionStatus rv = path_builder.Run(callback.closure());
988 ASSERT_EQ(CompletionStatus::ASYNC, rv);
989
990 ASSERT_FALSE(target_issuers_callback.is_null());
991
992 ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
993
994 // First async batch: return oldintermediary_.
995 EXPECT_CALL(*target_issuers_req, GetNext(_))
996 .WillOnce(DoAll(SetArgPointee<0>(oldintermediary_),
997 Return(CompletionStatus::SYNC)))
998 .WillOnce(
999 DoAll(SetArgPointee<0>(nullptr), Return(CompletionStatus::ASYNC)));
1000 {
1001 ::testing::InSequence s;
1002 // oldintermediary_ does not create a valid path, so both sync and async
1003 // lookups are expected.
1004 EXPECT_CALL(cert_issuer_source,
1005 SyncGetIssuersOf(oldintermediary_.get(), _));
1006 EXPECT_CALL(cert_issuer_source,
1007 AsyncGetIssuersOf(oldintermediary_.get(), _, _));
1008 }
1009 target_issuers_callback.Run(target_issuers_req);
1010 ::testing::Mock::VerifyAndClearExpectations(target_issuers_req);
1011 ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
1012
1013 // Second async batch: return a different copy of oldintermediary_ again.
1014 scoped_refptr<ParsedCertificate> oldintermediary_dupe(
1015 ParsedCertificate::CreateFromCertificateCopy(
1016 oldintermediary_->der_cert().AsStringPiece(), {}));
1017 EXPECT_CALL(*target_issuers_req, GetNext(_))
1018 .WillOnce(DoAll(SetArgPointee<0>(oldintermediary_dupe),
1019 Return(CompletionStatus::SYNC)))
1020 .WillOnce(
1021 DoAll(SetArgPointee<0>(nullptr), Return(CompletionStatus::ASYNC)));
1022 target_issuers_callback.Run(target_issuers_req);
1023 // oldintermediary was already processed above, it should not generate any
1024 // more requests.
1025 ::testing::Mock::VerifyAndClearExpectations(target_issuers_req);
1026 ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
1027
1028 // Third async batch: return newintermediary_.
1029 EXPECT_CALL(*target_issuers_req, GetNext(_))
1030 .WillOnce(DoAll(SetArgPointee<0>(newintermediary_),
1031 Return(CompletionStatus::SYNC)))
1032 .WillOnce(
1033 DoAll(SetArgPointee<0>(nullptr), Return(CompletionStatus::ASYNC)));
1034 // newroot_ is in the trust store, so this path will be completed
1035 // synchronously. AsyncGetIssuersOf will not be called on newintermediary_.
1036 EXPECT_CALL(cert_issuer_source, SyncGetIssuersOf(newintermediary_.get(), _));
1037 target_issuers_callback.Run(target_issuers_req);
1038 // Note that VerifyAndClearExpectations(target_issuers_req) is not called
1039 // here. PathBuilder could have destroyed it already, so just let the
1040 // expectations get checked by the destructor.
1041 ::testing::Mock::VerifyAndClearExpectations(&cert_issuer_source);
1042
1043 // Ensure pathbuilder finished and filled result.
1044 callback.WaitForResult();
1045
1046 EXPECT_EQ(OK, result.error());
1047 ASSERT_EQ(2U, result.paths.size());
1048
1049 // Path builder first attempts: target <- oldintermediary <- newroot
1050 // but it will fail since oldintermediary is signed by oldroot.
1051 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.paths[0]->error);
1052 ASSERT_EQ(3U, result.paths[0]->path.size());
1053 EXPECT_EQ(target_, result.paths[0]->path[0]);
1054 EXPECT_EQ(oldintermediary_, result.paths[0]->path[1]);
1055 EXPECT_EQ(newroot_, result.paths[0]->path[2]);
1056
1057 // The second async result does not generate any path.
1058
1059 // After the third batch of async results, path builder will attempt:
1060 // target <- newintermediary <- newroot which will succeed.
1061 EXPECT_EQ(OK, result.paths[1]->error);
1062 ASSERT_EQ(3U, result.paths[1]->path.size());
1063 EXPECT_EQ(target_, result.paths[1]->path[0]);
1064 EXPECT_EQ(newintermediary_, result.paths[1]->path[1]);
1065 EXPECT_EQ(newroot_, result.paths[1]->path[2]);
1066 }
1067
1068 } // namespace
1069
1070 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698