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

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

Powered by Google App Engine
This is Rietveld 408576698