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

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

Powered by Google App Engine
This is Rietveld 408576698