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

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: wip: Make CertPathIter build the full path including the trust anchor Created 4 years, 7 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/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/parse_certificate.h"
16 #include "net/cert/internal/parse_name.h"
17 #include "net/cert/internal/signature_policy.h"
18 #include "net/cert/internal/test_helpers.h"
19 #include "net/cert/internal/verify_certificate_chain.h"
20 #include "net/cert/pem_tokenizer.h"
21 #include "net/der/input.h"
22 #include "net/test/cert_test_util.h"
23 #include "net/test/test_certificate_data.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25
26 namespace net {
27
28 namespace {
29
30 // AsyncStaticCertSource always returns its certs asynchronously.
31 class AsyncStaticCertSource : public CertSource {
32 public:
33 class StaticAsyncRequest : public Request {
34 public:
35 StaticAsyncRequest(const IssuerCallback& issuers_callback,
36 CertVector&& issuers)
37 : cancelable_closure_(base::Bind(&StaticAsyncRequest::RunCallback,
38 base::Unretained(this))),
39 issuers_callback_(issuers_callback) {
40 issuers_.swap(issuers);
41 }
42 ~StaticAsyncRequest() override {}
43
44 void RunCallback() { issuers_callback_.Run(std::move(issuers_)); }
45 base::Closure callback() { return cancelable_closure_.callback(); }
46
47 private:
48 base::CancelableClosure cancelable_closure_;
49 IssuerCallback issuers_callback_;
50 CertVector issuers_;
51 AsyncStaticCertSource* source_;
52
53 DISALLOW_COPY_AND_ASSIGN(StaticAsyncRequest);
54 };
55
56 AsyncStaticCertSource(const CertVector& certs) : static_cert_source_(certs) {}
57 ~AsyncStaticCertSource() override {}
58
59 void SyncGetIssuersOf(const CertThing* cert, CertVector* issuers) override {}
60 int AsyncGetIssuersOf(const CertThing* cert,
61 const IssuerCallback& issuers_callback,
62 std::unique_ptr<Request>* out_req) override {
63 num_async_gets_++;
64 CertVector issuers;
65 static_cert_source_.SyncGetIssuersOf(cert, &issuers);
66 std::unique_ptr<StaticAsyncRequest> req(
67 new StaticAsyncRequest(issuers_callback, std::move(issuers)));
68 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, req->callback());
69 *out_req = std::move(req);
70 return ERR_IO_PENDING;
71 }
72 int num_async_gets() const { return num_async_gets_; }
73
74 private:
75 StaticCertSource static_cert_source_;
76
77 int num_async_gets_ = 0;
78 };
79
80 // Reads a data file from the unit-test data.
81 std::string ReadTestFileToString(const std::string& file_name) {
82 // Compute the full path, relative to the src/ directory.
83 base::FilePath src_root;
84 PathService::Get(base::DIR_SOURCE_ROOT, &src_root);
85 base::FilePath filepath = src_root.AppendASCII(file_name);
86
87 // Read the full contents of the file.
88 std::string file_data;
89 if (!base::ReadFileToString(filepath, &file_data)) {
90 ADD_FAILURE() << "Couldn't read file: " << filepath.value();
91 return std::string();
92 }
93
94 return file_data;
95 }
96
97 // Reads a verify_certificate_chain_unittest-style test case from |file_name|.
98 // Test cases are comprised of a certificate chain, trust store, a timestamp to
99 // validate at, and the expected result of verification (though the expected
100 // result is ignored here).
101 void ReadVerifyCertChainTestFromFile(const std::string& file_name,
102 std::vector<std::string>* chain,
103 scoped_refptr<CertThing>* root,
104 der::GeneralizedTime* time) {
105 chain->clear();
106
107 std::string file_data = ReadTestFileToString(file_name);
108
109 std::vector<std::string> pem_headers;
110
111 const char kCertificateHeader[] = "CERTIFICATE";
112 const char kTrustedCertificateHeader[] = "TRUSTED_CERTIFICATE";
113 const char kTimeHeader[] = "TIME";
114
115 pem_headers.push_back(kCertificateHeader);
116 pem_headers.push_back(kTrustedCertificateHeader);
117 pem_headers.push_back(kTimeHeader);
118
119 bool has_time = false;
120
121 PEMTokenizer pem_tokenizer(file_data, pem_headers);
122 while (pem_tokenizer.GetNext()) {
123 const std::string& block_type = pem_tokenizer.block_type();
124 const std::string& block_data = pem_tokenizer.data();
125
126 if (block_type == kCertificateHeader) {
127 chain->push_back(block_data);
128 } else if (block_type == kTrustedCertificateHeader) {
129 *root = CertThing::CreateFromCertificateCopy(block_data);
130 ASSERT_TRUE(*root);
131 } else if (block_type == kTimeHeader) {
132 ASSERT_FALSE(has_time) << "Duplicate " << kTimeHeader;
133 has_time = true;
134 ASSERT_TRUE(der::ParseUTCTime(der::Input(&block_data), time));
135 }
136 }
137
138 ASSERT_TRUE(has_time);
139 }
140
141 ::testing::AssertionResult ReadTestPem(const std::string& file_name,
142 const std::string& block_name,
143 std::string* result) {
144 const PemBlockMapping mappings[] = {
145 {block_name.c_str(), result},
146 };
147
148 return ReadTestDataFromPemFile(file_name, mappings);
149 }
150
151 ::testing::AssertionResult ReadTestCert(const std::string& file_name,
152 scoped_refptr<CertThing>* result) {
153 std::string der;
154 ::testing::AssertionResult r = ReadTestPem(
155 "net/data/ssl/certificates/" + file_name, "CERTIFICATE", &der);
156 if (!r)
157 return r;
158 *result = CertThing::CreateFromCertificateCopy(der);
159 if (!*result)
160 return ::testing::AssertionFailure() << "CreateFromCertificateCopy failed";
161 return ::testing::AssertionSuccess();
162 }
163
164 std::string DumpCertChain(const std::vector<scoped_refptr<CertThing>>& chain) {
165 std::string s;
166 for (const auto& i : chain) {
167 ParsedCertificate cert;
168 ParsedTbsCertificate tbs;
169 if (!ParseCertificate(i->der_cert(), &cert)) // XXX don't reparse
170 return std::string();
171 if (!ParseTbsCertificate(cert.tbs_certificate_tlv, &tbs))
172 return std::string();
173 RDNSequence subject, issuer;
174 if (!ParseName(tbs.subject_tlv, &subject))
175 return std::string();
176 if (!ParseName(tbs.issuer_tlv, &issuer))
177 return std::string();
178
179 std::string subject_str, issuer_str;
180
181 if (!ConvertToRFC2253(subject, &subject_str))
182 return std::string();
183 if (!ConvertToRFC2253(issuer, &issuer_str))
184 return std::string();
185 if (!s.empty())
186 s += " -> ";
187 s += subject_str + "(" + issuer_str + ")";
188 }
189 return s;
190 }
191
192 void DumpPathBuilderResults(const CertPathBuilder::Result& result) {
193 DVLOG(1) << "CertPathBuilder results (n=" << result.paths.size() << "):";
194 for (size_t i = 0; i < result.paths.size(); ++i) {
195 DVLOG(1) << " " << i << ((result.best_result_index == i) ? "*" : " ") << " "
196 << result.paths[i]->rv << " "
197 << DumpCertChain(result.paths[i]->path);
198 }
199 // DVLOG(1) << "result path: " << DumpCertChain(result.path);
200 }
201
202 class PathBuilderMultiRootTest : public ::testing::Test {
203 public:
204 PathBuilderMultiRootTest() : signature_policy_(1024) {}
205
206 void SetUp() override {
207 ASSERT_TRUE(ReadTestCert("multi-root-A-by-B.pem", &a_by_b_));
208 ASSERT_TRUE(ReadTestCert("multi-root-B-by-C.pem", &b_by_c_));
209 ASSERT_TRUE(ReadTestCert("multi-root-B-by-F.pem", &b_by_f_));
210 ASSERT_TRUE(ReadTestCert("multi-root-C-by-D.pem", &c_by_d_));
211 ASSERT_TRUE(ReadTestCert("multi-root-C-by-E.pem", &c_by_e_));
212 ASSERT_TRUE(ReadTestCert("multi-root-D-by-D.pem", &d_by_d_));
213 ASSERT_TRUE(ReadTestCert("multi-root-E-by-E.pem", &e_by_e_));
214 ASSERT_TRUE(ReadTestCert("multi-root-F-by-E.pem", &f_by_e_));
215 }
216
217 protected:
218 scoped_refptr<CertThing> a_by_b_, b_by_c_, b_by_f_, c_by_d_, c_by_e_, d_by_d_,
219 e_by_e_, f_by_e_;
220
221 SimpleSignaturePolicy signature_policy_;
222 der::GeneralizedTime time_ = {2016, 4, 11, 0, 0, 0};
223 };
224
225 // XXX
226 //
227 TEST_F(PathBuilderMultiRootTest, Simple) {
228 TrustStore trust_store;
229 trust_store.AddTrustedCertificate(b_by_f_);
230
231 CertPathBuilder::CertSources cert_sources;
232
233 scoped_refptr<CertThing> target_cert(a_by_b_);
234
235 CertPathBuilder::Result result;
236 CertPathBuilder path_builder(std::move(target_cert), cert_sources,
237 trust_store, &signature_policy_, time_, &result);
238
239 TestCompletionCallback callback;
240 int rv = path_builder.Run(callback.callback());
241
242 DVLOG(1) << "path_builder.Run rv=" << ErrorToString(rv);
243
244 EXPECT_EQ(OK, rv);
245
246 if (rv == ERR_IO_PENDING) {
247 DVLOG(1) << "waiting for async completion...";
248 rv = callback.WaitForResult();
249 DVLOG(1) << "async rv=" << ErrorToString(rv);
250 EXPECT_EQ(OK, rv);
251 }
252
253 // DVLOG(1) << "result path: " << DumpCertChain(result.path);
254 DumpPathBuilderResults(result);
255 }
256
257 // Test that async cert queries are not made if the path can be successfully
258 // built with synchronously available certs.
259 TEST_F(PathBuilderMultiRootTest, TriesSyncFirst) {
260 TrustStore trust_store;
261 trust_store.AddTrustedCertificate(e_by_e_);
262
263 CertVector sync_certs;
264 sync_certs.push_back(a_by_b_);
265 // XXX if B(C) is in certs, it may check that path first, which would try to
266 // do async query for issuers of C.
267 // sync_certs.push_back(b_by_c);
268 sync_certs.push_back(b_by_f_);
269 sync_certs.push_back(f_by_e_);
270 StaticCertSource sync_cert_source(sync_certs);
271
272 CertVector async_certs;
273 async_certs.push_back(b_by_c_);
274 async_certs.push_back(c_by_e_);
275 AsyncStaticCertSource async_cert_source(async_certs);
276
277 CertPathBuilder::CertSources cert_sources;
278 cert_sources.push_back(&async_cert_source);
279 cert_sources.push_back(&sync_cert_source);
280
281 scoped_refptr<CertThing> target_cert(a_by_b_);
282
283 CertPathBuilder::Result result;
284 CertPathBuilder path_builder(std::move(target_cert), cert_sources,
285 trust_store, &signature_policy_, time_, &result);
286
287 TestCompletionCallback callback;
288 int rv = path_builder.Run(callback.callback());
289
290 DVLOG(1) << "path_builder.Run rv=" << ErrorToString(rv);
291
292 EXPECT_EQ(OK, rv);
293
294 if (rv == ERR_IO_PENDING) {
295 DVLOG(1) << "waiting for async completion...";
296 rv = callback.WaitForResult();
297 DVLOG(1) << "async rv=" << ErrorToString(rv);
298 EXPECT_EQ(OK, rv);
299 }
300
301 // DVLOG(1) << "result path: " << DumpCertChain(result.path);
302 DumpPathBuilderResults(result);
303
304 EXPECT_EQ(0, async_cert_source.num_async_gets());
305 }
306
307 // If async queries are needed, all async sources will be queried
308 // simultaneously.
309 TEST_F(PathBuilderMultiRootTest, TestAsyncSimultaneous) {
310 TrustStore trust_store;
311 trust_store.AddTrustedCertificate(e_by_e_);
312
313 CertVector sync_certs;
314 sync_certs.push_back(a_by_b_);
315 sync_certs.push_back(b_by_c_);
316 sync_certs.push_back(b_by_f_);
317 StaticCertSource sync_cert_source(sync_certs);
318
319 CertVector async_certs1;
320 async_certs1.push_back(c_by_e_);
321 AsyncStaticCertSource async_cert_source1(async_certs1);
322
323 CertVector async_certs2;
324 async_certs2.push_back(f_by_e_);
325 AsyncStaticCertSource async_cert_source2(async_certs2);
326
327 CertPathBuilder::CertSources cert_sources;
328 cert_sources.push_back(&async_cert_source1);
329 cert_sources.push_back(&async_cert_source2);
330 cert_sources.push_back(&sync_cert_source);
331
332 scoped_refptr<CertThing> target_cert(a_by_b_);
333
334 CertPathBuilder::Result result;
335 CertPathBuilder path_builder(std::move(target_cert), cert_sources,
336 trust_store, &signature_policy_, time_, &result);
337
338 TestCompletionCallback callback;
339 int rv = path_builder.Run(callback.callback());
340
341 DVLOG(1) << "path_builder.Run rv=" << ErrorToString(rv);
342
343 EXPECT_EQ(ERR_IO_PENDING, rv);
344
345 if (rv == ERR_IO_PENDING) {
346 DVLOG(1) << "waiting for async completion...";
347 rv = callback.WaitForResult();
348 DVLOG(1) << "async rv=" << ErrorToString(rv);
349 EXPECT_EQ(OK, rv);
350 }
351
352 // DVLOG(1) << "result path: " << DumpCertChain(result.path);
353 DumpPathBuilderResults(result);
354
355 EXPECT_EQ(1, async_cert_source1.num_async_gets());
356 EXPECT_EQ(1, async_cert_source2.num_async_gets());
357 }
358
359 // Test that PathBuilder does not generate longer paths than necessary if one of
360 // the supplied certs is itself a trust anchor.
361 TEST_F(PathBuilderMultiRootTest, TestLongChain) {
362 // Both D(D) and C(D) are trusted roots.
363 TrustStore trust_store;
364 trust_store.AddTrustedCertificate(d_by_d_);
365 trust_store.AddTrustedCertificate(c_by_d_);
366
367 // Certs A(B), B(C), and C(D) are all supplied.
368 CertVector sync_certs;
369 sync_certs.push_back(a_by_b_);
370 sync_certs.push_back(b_by_c_);
371 sync_certs.push_back(c_by_d_);
372 StaticCertSource sync_cert_source(sync_certs);
373
374 CertPathBuilder::CertSources cert_sources;
375 cert_sources.push_back(&sync_cert_source);
376
377 scoped_refptr<CertThing> target_cert(a_by_b_);
378
379 CertPathBuilder::Result result;
380 CertPathBuilder path_builder(std::move(target_cert), cert_sources,
381 trust_store, &signature_policy_, time_, &result);
382
383 TestCompletionCallback callback;
384 int rv = path_builder.Run(callback.callback());
385
386 DVLOG(1) << "path_builder.Run rv=" << ErrorToString(rv);
387
388 EXPECT_EQ(OK, rv);
389
390 if (rv == ERR_IO_PENDING) {
391 DVLOG(1) << "waiting for async completion...";
392 rv = callback.WaitForResult();
393 DVLOG(1) << "async rv=" << ErrorToString(rv);
394 EXPECT_EQ(OK, rv);
395 }
396
397 // DVLOG(1) << "result path: " << DumpCertChain(result.path);
398 DumpPathBuilderResults(result);
399
400 // The result path should be A(B) -> B(C) -> C(D)
401 // not the longer but also valid A(B) -> B(C) -> C(D) -> D(D)
402
403 EXPECT_EQ(3U, result.paths[result.best_result_index]->path.size());
404 }
405
406 // Test that PathBuilder will backtrack and try a different path if the first
407 // one doesn't work out.
408 TEST_F(PathBuilderMultiRootTest, TestBacktracking) {
409 // Only D(D) is a trusted root.
410 TrustStore trust_store;
411 trust_store.AddTrustedCertificate(d_by_d_);
412
413 // Certs A(B), B(F), and F(E) are supplied synchronously, thus the path
414 // A(B) -> B(F) -> F(E) should be built first, though it won't verify.
415 CertVector sync_certs;
416 sync_certs.push_back(a_by_b_);
417 sync_certs.push_back(b_by_f_);
418 sync_certs.push_back(f_by_e_);
419 StaticCertSource sync_cert_source(sync_certs);
420
421 // Certs B(C), and C(D) are supplied asynchronously, so the path
422 // A(B) -> B(C) -> C(D) -> D(D) should be tried second.
423 CertVector async_certs;
424 async_certs.push_back(b_by_c_);
425 async_certs.push_back(c_by_d_);
426 AsyncStaticCertSource async_cert_source(async_certs);
427
428 CertPathBuilder::CertSources cert_sources;
429 cert_sources.push_back(&sync_cert_source);
430 cert_sources.push_back(&async_cert_source);
431
432 scoped_refptr<CertThing> target_cert(a_by_b_);
433
434 CertPathBuilder::Result result;
435 CertPathBuilder path_builder(std::move(target_cert), cert_sources,
436 trust_store, &signature_policy_, time_, &result);
437
438 TestCompletionCallback callback;
439 int rv = path_builder.Run(callback.callback());
440
441 DVLOG(1) << "path_builder.Run rv=" << ErrorToString(rv);
442
443 EXPECT_EQ(ERR_IO_PENDING, rv);
444
445 if (rv == ERR_IO_PENDING) {
446 DVLOG(1) << "waiting for async completion...";
447 rv = callback.WaitForResult();
448 DVLOG(1) << "async rv=" << ErrorToString(rv);
449 EXPECT_EQ(OK, rv);
450 }
451
452 // DVLOG(1) << "result path: " << DumpCertChain(result.path);
453 DumpPathBuilderResults(result);
454
455 // The result path should be A(B) -> B(C) -> C(D) -> D(D)
456 ASSERT_EQ(4U, result.paths[result.best_result_index]->path.size());
457 EXPECT_EQ(a_by_b_, result.paths[result.best_result_index]->path[0]);
458 EXPECT_EQ(b_by_c_, result.paths[result.best_result_index]->path[1]);
459 EXPECT_EQ(c_by_d_, result.paths[result.best_result_index]->path[2]);
460 EXPECT_EQ(d_by_d_, result.paths[result.best_result_index]->path[3]);
461 }
462
463 class PathBuilderKeyRolloverTest : public ::testing::Test {
464 public:
465 PathBuilderKeyRolloverTest() : signature_policy_(1024) {}
466
467 void SetUp() override {
468 std::vector<std::string> path;
469
470 ReadVerifyCertChainTestFromFile(
471 "net/data/verify_certificate_chain_unittest/key-rollover-oldchain.pem",
472 &path, &oldroot_, &time_);
473 ASSERT_EQ(2U, path.size());
474 target_ = CertThing::CreateFromCertificateCopy(path[0]);
475 oldintermediary_ = CertThing::CreateFromCertificateCopy(path[1]);
476 ASSERT_TRUE(target_);
477 ASSERT_TRUE(oldintermediary_);
478
479 ReadVerifyCertChainTestFromFile(
480 "net/data/verify_certificate_chain_unittest/"
481 "key-rollover-longrolloverchain.pem",
482 &path, &oldroot_, &time_);
483 ASSERT_EQ(4U, path.size());
484 newintermediary_ = CertThing::CreateFromCertificateCopy(path[1]);
485 newroot_ = CertThing::CreateFromCertificateCopy(path[2]);
486 newrootrollover_ = CertThing::CreateFromCertificateCopy(path[3]);
487 ASSERT_TRUE(newintermediary_);
488 ASSERT_TRUE(newroot_);
489 ASSERT_TRUE(newrootrollover_);
490 }
491
492 protected:
493 scoped_refptr<CertThing> target_, oldintermediary_, newintermediary_,
494 oldroot_, newroot_, newrootrollover_;
495
496 SimpleSignaturePolicy signature_policy_;
497 der::GeneralizedTime time_;
498 };
499
500 // Tests that if only the old root cert is trusted, the path builder can build a
501 // path through the new intermediate and rollover cert to the old root.
502 TEST_F(PathBuilderKeyRolloverTest, TestRolloverOnlyOldRootTrusted) {
503 // Only oldroot is trusted.
504 TrustStore trust_store;
505 trust_store.AddTrustedCertificate(oldroot_);
506
507 // Old intermediary cert is not provided, so the pathbuilder will need to go
508 // through the rollover cert.
509 CertVector sync_certs;
510 sync_certs.push_back(newintermediary_);
511 sync_certs.push_back(newrootrollover_);
512 StaticCertSource sync_cert_source(sync_certs);
513
514 CertPathBuilder::CertSources cert_sources;
515 cert_sources.push_back(&sync_cert_source);
516
517 scoped_refptr<CertThing> target_cert(target_);
518
519 CertPathBuilder::Result result;
520 CertPathBuilder path_builder(std::move(target_cert), cert_sources,
521 trust_store, &signature_policy_, time_, &result);
522
523 TestCompletionCallback callback;
524 int rv = path_builder.Run(callback.callback());
525
526 DVLOG(1) << "path_builder.Run rv=" << ErrorToString(rv);
527
528 EXPECT_EQ(OK, rv);
529
530 if (rv == ERR_IO_PENDING) {
531 DVLOG(1) << "waiting for async completion...";
532 rv = callback.WaitForResult();
533 DVLOG(1) << "async rv=" << ErrorToString(rv);
534 EXPECT_EQ(OK, rv);
535 }
536
537 DumpPathBuilderResults(result);
538
539 // Path builder will first attempt: target -> newintermediary -> oldroot
540 // but it will fail since newintermediary is signed by newroot.
541 ASSERT_EQ(2U, result.paths.size());
542 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.paths[0]->rv);
543 ASSERT_EQ(3U, result.paths[0]->path.size());
544 EXPECT_EQ(target_, result.paths[0]->path[0]);
545 EXPECT_EQ(newintermediary_, result.paths[0]->path[1]);
546 EXPECT_EQ(oldroot_, result.paths[0]->path[2]);
547
548 // Path builder will next attempt:
549 // target -> newintermediary -> newrootrollover -> oldroot
550 // which will succeed.
551 EXPECT_EQ(1U, result.best_result_index);
552 EXPECT_EQ(OK, result.paths[1]->rv);
553 ASSERT_EQ(4U, result.paths[1]->path.size());
554 EXPECT_EQ(target_, result.paths[1]->path[0]);
555 EXPECT_EQ(newintermediary_, result.paths[1]->path[1]);
556 EXPECT_EQ(newrootrollover_, result.paths[1]->path[2]);
557 EXPECT_EQ(oldroot_, result.paths[1]->path[3]);
558 }
559
560 // Tests that if both old and new roots are trusted it can build a path through
561 // either.
562 // XXX Once prioritzation is implemented, it should test that it always builds
563 // the path through the new root.
564 TEST_F(PathBuilderKeyRolloverTest, TestRolloverBothRootsTrusted) {
565 // Both oldroot and newroot are trusted.
566 TrustStore trust_store;
567 trust_store.AddTrustedCertificate(oldroot_);
568 trust_store.AddTrustedCertificate(newroot_);
569
570 // Both old and new intermediates + rollover cert are provided.
571 CertVector sync_certs;
572 sync_certs.push_back(oldintermediary_);
573 sync_certs.push_back(newintermediary_);
574 sync_certs.push_back(newrootrollover_);
575 StaticCertSource sync_cert_source(sync_certs);
576
577 CertPathBuilder::CertSources cert_sources;
578 cert_sources.push_back(&sync_cert_source);
579
580 scoped_refptr<CertThing> target_cert(target_);
581
582 CertPathBuilder::Result result;
583 CertPathBuilder path_builder(std::move(target_cert), cert_sources,
584 trust_store, &signature_policy_, time_, &result);
585
586 TestCompletionCallback callback;
587 int rv = path_builder.Run(callback.callback());
588
589 DVLOG(1) << "path_builder.Run rv=" << ErrorToString(rv);
590
591 EXPECT_EQ(OK, rv);
592
593 if (rv == ERR_IO_PENDING) {
594 DVLOG(1) << "waiting for async completion...";
595 rv = callback.WaitForResult();
596 DVLOG(1) << "async rv=" << ErrorToString(rv);
597 EXPECT_EQ(OK, rv);
598 }
599
600 DumpPathBuilderResults(result);
601
602 // Path builder willattempt one of:
603 // target -> oldintermediary -> oldroot
604 // target -> newintermediary -> newroot
605 // either will succeed.
606 ASSERT_EQ(1U, result.paths.size());
607 EXPECT_EQ(OK, result.paths[0]->rv);
608 ASSERT_EQ(3U, result.paths[0]->path.size());
609 EXPECT_EQ(target_, result.paths[0]->path[0]);
610 // TODO: once we sort input certs on notbefore date, verify that it prefers
611 // newintermediary.
612 if (result.paths[0]->path[1] != newintermediary_) {
613 DVLOG(1) << "USED OLD";
614 EXPECT_EQ(oldintermediary_, result.paths[0]->path[1]);
615 EXPECT_EQ(oldroot_, result.paths[0]->path[2]);
616 } else {
617 DVLOG(1) << "USED NEW";
618 EXPECT_EQ(newintermediary_, result.paths[0]->path[1]);
619 EXPECT_EQ(newroot_, result.paths[0]->path[2]);
620 }
621 }
622
623 // Tests that the path builder doesn't build longer than necessary paths.
624 TEST_F(PathBuilderKeyRolloverTest, TestRolloverLongChain) {
625 // Only oldroot is trusted.
626 TrustStore trust_store;
627 trust_store.AddTrustedCertificate(oldroot_);
628
629 // New intermediate and new root are provided synchronously.
630 CertVector sync_certs;
631 sync_certs.push_back(newintermediary_);
632 sync_certs.push_back(newroot_);
633 StaticCertSource sync_cert_source(sync_certs);
634
635 // Rollover cert is only provided asynchronously. This will force the
636 // pathbuilder to first try building a longer than necessary path.
637 CertVector async_certs;
638 async_certs.push_back(newrootrollover_);
639 AsyncStaticCertSource async_cert_source(async_certs);
640
641 CertPathBuilder::CertSources cert_sources;
642 cert_sources.push_back(&sync_cert_source);
643 cert_sources.push_back(&async_cert_source);
644
645 scoped_refptr<CertThing> target_cert(target_);
646
647 CertPathBuilder::Result result;
648 CertPathBuilder path_builder(std::move(target_cert), cert_sources,
649 trust_store, &signature_policy_, time_, &result);
650
651 TestCompletionCallback callback;
652 int rv = path_builder.Run(callback.callback());
653
654 DVLOG(1) << "path_builder.Run rv=" << ErrorToString(rv);
655
656 EXPECT_EQ(ERR_IO_PENDING, rv);
657
658 if (rv == ERR_IO_PENDING) {
659 DVLOG(1) << "waiting for async completion...";
660 rv = callback.WaitForResult();
661 DVLOG(1) << "async rv=" << ErrorToString(rv);
662 EXPECT_EQ(OK, rv);
663 }
664
665 DumpPathBuilderResults(result);
666
667 ASSERT_EQ(3U, result.paths.size());
668
669 // Path builder will first attempt: target -> newintermediary -> oldroot
670 // but it will fail since newintermediary is signed by newroot.
671 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.paths[0]->rv);
672 ASSERT_EQ(3U, result.paths[0]->path.size());
673 EXPECT_EQ(target_, result.paths[0]->path[0]);
674 EXPECT_EQ(newintermediary_, result.paths[0]->path[1]);
675 EXPECT_EQ(oldroot_, result.paths[0]->path[2]);
676
677 // Path builder will next attempt: target -> newintermediary -> newroot ->
678 // oldroot
679 // but it will fail since newroot is self-signed.
680 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, result.paths[1]->rv);
681 ASSERT_EQ(4U, result.paths[1]->path.size());
682 EXPECT_EQ(target_, result.paths[1]->path[0]);
683 EXPECT_EQ(newintermediary_, result.paths[1]->path[1]);
684 EXPECT_EQ(newroot_, result.paths[1]->path[2]);
685 EXPECT_EQ(oldroot_, result.paths[1]->path[3]);
686
687 // Path builder will skip:
688 // target -> newintermediary -> newroot -> newrootrollover -> ...
689 // Since newroot and newrootrollover have the same Name+SAN+SPKI.
690
691 // Finally path builder will use:
692 // target -> newintermediary -> newrootrollover -> oldroot
693 EXPECT_EQ(2U, result.best_result_index);
694 EXPECT_EQ(OK, result.paths[2]->rv);
695 ASSERT_EQ(4U, result.paths[2]->path.size());
696 EXPECT_EQ(target_, result.paths[2]->path[0]);
697 EXPECT_EQ(newintermediary_, result.paths[2]->path[1]);
698 EXPECT_EQ(newrootrollover_, result.paths[2]->path[2]);
699 EXPECT_EQ(oldroot_, result.paths[2]->path[3]);
700 }
701
702 // If the target cert is a trust root, that alone is a valid path.
703 TEST_F(PathBuilderKeyRolloverTest, TestEndEntityIsTrustRoot) {
704 // Trust newintermediary.
705 TrustStore trust_store;
706 trust_store.AddTrustedCertificate(newintermediary_);
707
708 // No certsources needed for this test.
709 CertPathBuilder::CertSources cert_sources;
710
711 // Newintermediary is also the target cert.
712 scoped_refptr<CertThing> target_cert(newintermediary_);
713
714 CertPathBuilder::Result result;
715 CertPathBuilder path_builder(std::move(target_cert), cert_sources,
716 trust_store, &signature_policy_, time_, &result);
717
718 TestCompletionCallback callback;
719 int rv = path_builder.Run(callback.callback());
720
721 DVLOG(1) << "path_builder.Run rv=" << ErrorToString(rv);
722
723 EXPECT_EQ(OK, rv);
724
725 if (rv == ERR_IO_PENDING) {
726 DVLOG(1) << "waiting for async completion...";
727 rv = callback.WaitForResult();
728 DVLOG(1) << "async rv=" << ErrorToString(rv);
729 EXPECT_EQ(OK, rv);
730 }
731
732 DumpPathBuilderResults(result);
733
734 ASSERT_EQ(1U, result.paths.size());
735 EXPECT_EQ(OK, result.paths[0]->rv);
736 ASSERT_EQ(1U, result.paths[0]->path.size());
737 EXPECT_EQ(newintermediary_, result.paths[0]->path[0]);
738 }
739
740 // If target has same Name+SAN+SPKI as a necessary intermediate, test that a
741 // path can still be built.
742 TEST_F(PathBuilderKeyRolloverTest,
743 TestEndEntityHasSameNameAndSpkiAsIntermediate) {
744 // Trust oldroot.
745 TrustStore trust_store;
746 trust_store.AddTrustedCertificate(oldroot_);
747
748 // New root rollover is provided synchronously.
749 CertVector sync_certs;
750 sync_certs.push_back(newrootrollover_);
751 StaticCertSource sync_cert_source(sync_certs);
752
753 CertPathBuilder::CertSources cert_sources;
754 cert_sources.push_back(&sync_cert_source);
755
756 // Newroot is the target cert.
757 scoped_refptr<CertThing> target_cert(newroot_);
758
759 CertPathBuilder::Result result;
760 CertPathBuilder path_builder(std::move(target_cert), cert_sources,
761 trust_store, &signature_policy_, time_, &result);
762
763 TestCompletionCallback callback;
764 int rv = path_builder.Run(callback.callback());
765
766 DVLOG(1) << "path_builder.Run rv=" << ErrorToString(rv);
767
768 EXPECT_EQ(OK, rv);
769
770 if (rv == ERR_IO_PENDING) {
771 DVLOG(1) << "waiting for async completion...";
772 rv = callback.WaitForResult();
773 DVLOG(1) << "async rv=" << ErrorToString(rv);
774 EXPECT_EQ(OK, rv);
775 }
776
777 DumpPathBuilderResults(result);
778
779 ASSERT_FALSE(result.paths.empty());
780 const CertPathBuilder::ResultPath* best_result =
781 result.paths[result.best_result_index].get();
782
783 EXPECT_EQ(OK, best_result->rv);
784 ASSERT_EQ(3U, best_result->path.size());
785 EXPECT_EQ(newroot_, best_result->path[0]);
786 EXPECT_EQ(newrootrollover_, best_result->path[1]);
787 EXPECT_EQ(oldroot_, best_result->path[2]);
788 }
789
790 // If target has same Name+SAN+SPKI as the trust root, test that a path can
791 // still be built.
792 TEST_F(PathBuilderKeyRolloverTest,
793 TestEndEntityHasSameNameAndSpkiAsTrustAnchor) {
794 // Trust newrootrollover.
795 TrustStore trust_store;
796 trust_store.AddTrustedCertificate(newrootrollover_);
797
798 // No certsources.
799 CertPathBuilder::CertSources cert_sources;
800
801 // Newroot is the target cert.
802 scoped_refptr<CertThing> target_cert(newroot_);
803
804 CertPathBuilder::Result result;
805 CertPathBuilder path_builder(std::move(target_cert), cert_sources,
806 trust_store, &signature_policy_, time_, &result);
807
808 TestCompletionCallback callback;
809 int rv = path_builder.Run(callback.callback());
810
811 DVLOG(1) << "path_builder.Run rv=" << ErrorToString(rv);
812
813 EXPECT_EQ(OK, rv);
814
815 if (rv == ERR_IO_PENDING) {
816 DVLOG(1) << "waiting for async completion...";
817 rv = callback.WaitForResult();
818 DVLOG(1) << "async rv=" << ErrorToString(rv);
819 EXPECT_EQ(OK, rv);
820 }
821
822 DumpPathBuilderResults(result);
823
824 ASSERT_FALSE(result.paths.empty());
825 const CertPathBuilder::ResultPath* best_result =
826 result.paths[result.best_result_index].get();
827
828 EXPECT_EQ(OK, best_result->rv);
829 ASSERT_EQ(2U, best_result->path.size());
830 EXPECT_EQ(newroot_, best_result->path[0]);
831 EXPECT_EQ(newrootrollover_, best_result->path[1]);
832 }
833
834 // TODO:
835 // * cross signing ?
836 // * test of multiple trust anchor matches
837
838 } // namespace
839
840 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698