1 // Copyright 2018 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 "content/browser/web_package/signed_exchange_cert_fetcher.h"
6
7 #include "base/base64.h"
8 #include "base/bind.h"
9 #include "base/callback.h"
10 #include "base/optional.h"
11 #include "base/strings/string_piece.h"
12 #include "base/test/task_environment.h"
13 #include "components/cbor/values.h"
14 #include "components/cbor/writer.h"
15 #include "mojo/public/cpp/bindings/pending_remote.h"
16 #include "mojo/public/cpp/bindings/receiver.h"
17 #include "mojo/public/cpp/bindings/remote.h"
18 #include "mojo/public/cpp/system/data_pipe_utils.h"
19 #include "net/base/load_flags.h"
20 #include "net/cert/x509_util.h"
21 #include "net/test/cert_test_util.h"
22 #include "net/test/test_data_directory.h"
23 #include "services/network/public/cpp/features.h"
24 #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
25 #include "services/network/public/mojom/url_loader_factory.mojom.h"
26 #include "services/network/public/mojom/url_response_head.mojom.h"
27 #include "testing/gmock/include/gmock/gmock.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29 #include "third_party/blink/public/common/loader/url_loader_throttle.h"
30 #include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
31
32 namespace content {
33
34 namespace {
35
36 class DeferringURLLoaderThrottle final : public blink::URLLoaderThrottle {
37 public:
38 DeferringURLLoaderThrottle() = default;
39 ~DeferringURLLoaderThrottle() override = default;
40
WillStartRequest(network::ResourceRequest * request,bool * defer)41 void WillStartRequest(network::ResourceRequest* request,
42 bool* defer) override {
43 will_start_request_called_ = true;
44 *defer = true;
45 }
46
WillRedirectRequest(net::RedirectInfo * redirect_info,const network::mojom::URLResponseHead &,bool * defer,std::vector<std::string> *,net::HttpRequestHeaders *)47 void WillRedirectRequest(
48 net::RedirectInfo* redirect_info,
49 const network::mojom::URLResponseHead& /* response_head */,
50 bool* defer,
51 std::vector<std::string>* /* to_be_removed_headers */,
52 net::HttpRequestHeaders* /* modified_headers */) override {
53 will_redirect_request_called_ = true;
54 *defer = true;
55 }
56
WillProcessResponse(const GURL & response_url_,network::mojom::URLResponseHead * response_head,bool * defer)57 void WillProcessResponse(const GURL& response_url_,
58 network::mojom::URLResponseHead* response_head,
59 bool* defer) override {
60 will_process_response_called_ = true;
61 *defer = true;
62 }
63
will_start_request_called() const64 bool will_start_request_called() const { return will_start_request_called_; }
will_redirect_request_called() const65 bool will_redirect_request_called() const {
66 return will_redirect_request_called_;
67 }
will_process_response_called() const68 bool will_process_response_called() const {
69 return will_process_response_called_;
70 }
71
delegate()72 Delegate* delegate() { return delegate_; }
73
74 private:
75 bool will_start_request_called_ = false;
76 bool will_redirect_request_called_ = false;
77 bool will_process_response_called_ = false;
78
79 DISALLOW_COPY_AND_ASSIGN(DeferringURLLoaderThrottle);
80 };
81
82 class MockURLLoader final : public network::mojom::URLLoader {
83 public:
MockURLLoader(mojo::PendingReceiver<network::mojom::URLLoader> url_loader_receiver)84 MockURLLoader(
85 mojo::PendingReceiver<network::mojom::URLLoader> url_loader_receiver)
86 : receiver_(this, std::move(url_loader_receiver)) {}
87 ~MockURLLoader() override = default;
88
89 MOCK_METHOD3(FollowRedirect,
90 void(const std::vector<std::string>&,
91 const net::HttpRequestHeaders&,
92 const base::Optional<GURL>&));
93 MOCK_METHOD2(SetPriority,
94 void(net::RequestPriority priority,
95 int32_t intra_priority_value));
96 MOCK_METHOD0(PauseReadingBodyFromNet, void());
97 MOCK_METHOD0(ResumeReadingBodyFromNet, void());
98
99 private:
100 mojo::Receiver<network::mojom::URLLoader> receiver_;
101
102 DISALLOW_COPY_AND_ASSIGN(MockURLLoader);
103 };
104
105 class URLLoaderFactoryForMockLoader final
106 : public network::mojom::URLLoaderFactory {
107 public:
108 URLLoaderFactoryForMockLoader() = default;
109 ~URLLoaderFactoryForMockLoader() override = default;
110
111 // network::mojom::URLLoaderFactory implementation.
CreateLoaderAndStart(mojo::PendingReceiver<network::mojom::URLLoader> url_loader_receiver,int32_t routing_id,int32_t request_id,uint32_t options,const network::ResourceRequest & url_request,mojo::PendingRemote<network::mojom::URLLoaderClient> client,const net::MutableNetworkTrafficAnnotationTag & traffic_annotation)112 void CreateLoaderAndStart(
113 mojo::PendingReceiver<network::mojom::URLLoader> url_loader_receiver,
114 int32_t routing_id,
115 int32_t request_id,
116 uint32_t options,
117 const network::ResourceRequest& url_request,
118 mojo::PendingRemote<network::mojom::URLLoaderClient> client,
119 const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
120 override {
121 loader_ = std::make_unique<MockURLLoader>(std::move(url_loader_receiver));
122 url_request_ = url_request;
123 client_remote_.Bind(std::move(client));
124 }
125
Clone(mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory)126 void Clone(mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory)
127 override {
128 NOTREACHED();
129 }
130
client_remote()131 mojo::Remote<network::mojom::URLLoaderClient>& client_remote() {
132 return client_remote_;
133 }
CloseClientPipe()134 void CloseClientPipe() { client_remote_.reset(); }
135
url_request() const136 base::Optional<network::ResourceRequest> url_request() const {
137 return url_request_;
138 }
139
140 private:
141 std::unique_ptr<MockURLLoader> loader_;
142 mojo::Remote<network::mojom::URLLoaderClient> client_remote_;
143 base::Optional<network::ResourceRequest> url_request_;
144
145 DISALLOW_COPY_AND_ASSIGN(URLLoaderFactoryForMockLoader);
146 };
147
ForwardCertificateCallback(bool * called,SignedExchangeLoadResult * out_result,std::unique_ptr<SignedExchangeCertificateChain> * out_cert,SignedExchangeLoadResult result,std::unique_ptr<SignedExchangeCertificateChain> cert_chain)148 void ForwardCertificateCallback(
149 bool* called,
150 SignedExchangeLoadResult* out_result,
151 std::unique_ptr<SignedExchangeCertificateChain>* out_cert,
152 SignedExchangeLoadResult result,
153 std::unique_ptr<SignedExchangeCertificateChain> cert_chain) {
154 *out_result = result;
155 *called = true;
156 *out_cert = std::move(cert_chain);
157 }
158
159 class SignedExchangeCertFetcherTest : public testing::Test {
160 public:
SignedExchangeCertFetcherTest()161 SignedExchangeCertFetcherTest()
162 : url_(GURL("https://www.example.com/cert")) {}
~SignedExchangeCertFetcherTest()163 ~SignedExchangeCertFetcherTest() override {}
164
165 protected:
ImportTestCert()166 static scoped_refptr<net::X509Certificate> ImportTestCert() {
167 return net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
168 }
169
CreateCertMessage(const base::StringPiece & cert_data)170 static std::string CreateCertMessage(const base::StringPiece& cert_data) {
171 cbor::Value::MapValue cbor_map;
172 cbor_map[cbor::Value("sct")] =
173 cbor::Value("SCT", cbor::Value::Type::BYTE_STRING);
174 cbor_map[cbor::Value("cert")] =
175 cbor::Value(cert_data, cbor::Value::Type::BYTE_STRING);
176 cbor_map[cbor::Value("ocsp")] =
177 cbor::Value("OCSP", cbor::Value::Type::BYTE_STRING);
178
179 cbor::Value::ArrayValue cbor_array;
180 cbor_array.push_back(cbor::Value(u8"\U0001F4DC\u26D3"));
181 cbor_array.push_back(cbor::Value(std::move(cbor_map)));
182
183 base::Optional<std::vector<uint8_t>> serialized =
184 cbor::Writer::Write(cbor::Value(std::move(cbor_array)));
185 if (!serialized)
186 return std::string();
187 return std::string(reinterpret_cast<char*>(serialized->data()),
188 serialized->size());
189 }
190
CreateCertMessageFromCert(const net::X509Certificate & cert)191 static base::StringPiece CreateCertMessageFromCert(
192 const net::X509Certificate& cert) {
193 return net::x509_util::CryptoBufferAsStringPiece(cert.cert_buffer());
194 }
195
CreateTestData()196 static std::string CreateTestData() {
197 scoped_refptr<net::X509Certificate> certificate = ImportTestCert();
198 return CreateCertMessage(CreateCertMessageFromCert(*certificate));
199 }
200
CreateTestDataFilledDataPipe()201 static mojo::ScopedDataPipeConsumerHandle CreateTestDataFilledDataPipe() {
202 auto message = CreateTestData();
203 mojo::DataPipe data_pipe(message.size());
204 CHECK(mojo::BlockingCopyFromString(message, data_pipe.producer_handle));
205 return std::move(data_pipe.consumer_handle);
206 }
207
GetTestDataCertFingerprint256()208 static net::SHA256HashValue GetTestDataCertFingerprint256() {
209 return ImportTestCert()->CalculateChainFingerprint256();
210 }
211
RunUntilIdle()212 void RunUntilIdle() { task_environment_.RunUntilIdle(); }
213
CreateFetcherAndStart(const GURL & url,bool force_fetch)214 std::unique_ptr<SignedExchangeCertFetcher> CreateFetcherAndStart(
215 const GURL& url,
216 bool force_fetch) {
217 SignedExchangeCertFetcher::CertificateCallback callback = base::BindOnce(
218 &ForwardCertificateCallback, base::Unretained(&callback_called_),
219 base::Unretained(&result_), base::Unretained(&cert_result_));
220
221 return SignedExchangeCertFetcher::CreateAndStart(
222 base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
223 &mock_loader_factory_),
224 std::move(throttles_), url, force_fetch, std::move(callback),
225 nullptr /* devtools_proxy */, nullptr /* reporter */,
226 base::nullopt /* throttling_profile_id */,
227 base::nullopt /* network_isolation_key */);
228 }
229
CallOnReceiveResponse()230 void CallOnReceiveResponse() {
231 auto response_head = network::mojom::URLResponseHead::New();
232 response_head->headers =
233 base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK");
234 response_head->headers->AddHeader(
235 "Content-Type: application/cert-chain+cbor");
236 response_head->mime_type = "application/cert-chain+cbor";
237 mock_loader_factory_.client_remote()->OnReceiveResponse(
238 std::move(response_head));
239 }
240
InitializeDeferringURLLoaderThrottle()241 DeferringURLLoaderThrottle* InitializeDeferringURLLoaderThrottle() {
242 std::unique_ptr<DeferringURLLoaderThrottle> throttle =
243 std::make_unique<DeferringURLLoaderThrottle>();
244 DeferringURLLoaderThrottle* ptr = throttle.get();
245 throttles_.push_back(std::move(throttle));
246 return ptr;
247 }
248
CloseClientPipe()249 void CloseClientPipe() { mock_loader_factory_.CloseClientPipe(); }
250
251 const GURL url_;
252 bool callback_called_ = false;
253 SignedExchangeLoadResult result_;
254 std::unique_ptr<SignedExchangeCertificateChain> cert_result_;
255 URLLoaderFactoryForMockLoader mock_loader_factory_;
256 std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles_;
257
258 base::test::TaskEnvironment task_environment_;
259
260 private:
261 DISALLOW_COPY_AND_ASSIGN(SignedExchangeCertFetcherTest);
262 };
263
264 } // namespace
265
TEST_F(SignedExchangeCertFetcherTest,Simple)266 TEST_F(SignedExchangeCertFetcherTest, Simple) {
267 std::unique_ptr<SignedExchangeCertFetcher> fetcher =
268 CreateFetcherAndStart(url_, false /* force_fetch */);
269
270 ASSERT_TRUE(mock_loader_factory_.client_remote());
271 ASSERT_TRUE(mock_loader_factory_.url_request());
272 EXPECT_EQ(url_, mock_loader_factory_.url_request()->url);
273 EXPECT_EQ(static_cast<int>(blink::mojom::ResourceType::kSubResource),
274 mock_loader_factory_.url_request()->resource_type);
275 EXPECT_EQ(mock_loader_factory_.url_request()->credentials_mode,
276 network::mojom::CredentialsMode::kOmit);
277 EXPECT_TRUE(mock_loader_factory_.url_request()->request_initiator->opaque());
278 std::string accept;
279 EXPECT_TRUE(
280 mock_loader_factory_.url_request()->headers.GetHeader("Accept", &accept));
281 EXPECT_EQ("application/cert-chain+cbor", accept);
282
283 CallOnReceiveResponse();
284 mock_loader_factory_.client_remote()->OnStartLoadingResponseBody(
285 CreateTestDataFilledDataPipe());
286 mock_loader_factory_.client_remote()->OnComplete(
287 network::URLLoaderCompletionStatus(net::OK));
288 RunUntilIdle();
289 EXPECT_TRUE(callback_called_);
290 EXPECT_EQ(SignedExchangeLoadResult::kSuccess, result_);
291 ASSERT_TRUE(cert_result_);
292 EXPECT_EQ(GetTestDataCertFingerprint256(),
293 cert_result_->cert()->CalculateChainFingerprint256());
294 }
295
TEST_F(SignedExchangeCertFetcherTest,MultipleChunked)296 TEST_F(SignedExchangeCertFetcherTest, MultipleChunked) {
297 std::unique_ptr<SignedExchangeCertFetcher> fetcher =
298 CreateFetcherAndStart(url_, false /* force_fetch */);
299 CallOnReceiveResponse();
300 scoped_refptr<net::X509Certificate> certificate = ImportTestCert();
301 const std::string message =
302 CreateCertMessage(CreateCertMessageFromCert(*certificate));
303 mojo::DataPipe data_pipe(message.size() / 2 + 1);
304 ASSERT_TRUE(mojo::BlockingCopyFromString(
305 message.substr(0, message.size() / 2), data_pipe.producer_handle));
306 mock_loader_factory_.client_remote()->OnStartLoadingResponseBody(
307 std::move(data_pipe.consumer_handle));
308 RunUntilIdle();
309 ASSERT_TRUE(mojo::BlockingCopyFromString(message.substr(message.size() / 2),
310 data_pipe.producer_handle));
311 data_pipe.producer_handle.reset();
312 mock_loader_factory_.client_remote()->OnComplete(
313 network::URLLoaderCompletionStatus(net::OK));
314 RunUntilIdle();
315
316 EXPECT_TRUE(callback_called_);
317 EXPECT_EQ(SignedExchangeLoadResult::kSuccess, result_);
318 ASSERT_TRUE(cert_result_);
319 EXPECT_EQ(certificate->CalculateChainFingerprint256(),
320 cert_result_->cert()->CalculateChainFingerprint256());
321 }
322
TEST_F(SignedExchangeCertFetcherTest,ForceFetchAndFail)323 TEST_F(SignedExchangeCertFetcherTest, ForceFetchAndFail) {
324 std::unique_ptr<SignedExchangeCertFetcher> fetcher =
325 CreateFetcherAndStart(url_, true /* force_fetch */);
326 CallOnReceiveResponse();
327
328 ASSERT_TRUE(mock_loader_factory_.url_request());
329 EXPECT_EQ(url_, mock_loader_factory_.url_request()->url);
330 EXPECT_EQ(static_cast<int>(blink::mojom::ResourceType::kSubResource),
331 mock_loader_factory_.url_request()->resource_type);
332 EXPECT_EQ(net::LOAD_DISABLE_CACHE | net::LOAD_BYPASS_CACHE,
333 mock_loader_factory_.url_request()->load_flags);
334 EXPECT_EQ(mock_loader_factory_.url_request()->credentials_mode,
335 network::mojom::CredentialsMode::kOmit);
336
337 mock_loader_factory_.client_remote()->OnComplete(
338 network::URLLoaderCompletionStatus(net::ERR_INVALID_SIGNED_EXCHANGE));
339 RunUntilIdle();
340
341 EXPECT_TRUE(callback_called_);
342 EXPECT_EQ(SignedExchangeLoadResult::kCertFetchError, result_);
343 EXPECT_FALSE(cert_result_);
344 }
345
TEST_F(SignedExchangeCertFetcherTest,MaxCertSize_Exceeds)346 TEST_F(SignedExchangeCertFetcherTest, MaxCertSize_Exceeds) {
347 scoped_refptr<net::X509Certificate> certificate = ImportTestCert();
348 const std::string message =
349 CreateCertMessage(CreateCertMessageFromCert(*certificate));
350 base::ScopedClosureRunner reset_max =
351 SignedExchangeCertFetcher::SetMaxCertSizeForTest(message.size() - 1);
352
353 std::unique_ptr<SignedExchangeCertFetcher> fetcher =
354 CreateFetcherAndStart(url_, false /* force_fetch */);
355 CallOnReceiveResponse();
356 mojo::DataPipe data_pipe(message.size());
357 CHECK(mojo::BlockingCopyFromString(message, data_pipe.producer_handle));
358 data_pipe.producer_handle.reset();
359 mock_loader_factory_.client_remote()->OnStartLoadingResponseBody(
360 std::move(data_pipe.consumer_handle));
361 mock_loader_factory_.client_remote()->OnComplete(
362 network::URLLoaderCompletionStatus(net::OK));
363 RunUntilIdle();
364
365 EXPECT_TRUE(callback_called_);
366 EXPECT_EQ(SignedExchangeLoadResult::kCertFetchError, result_);
367 EXPECT_FALSE(cert_result_);
368 }
369
TEST_F(SignedExchangeCertFetcherTest,MaxCertSize_SameSize)370 TEST_F(SignedExchangeCertFetcherTest, MaxCertSize_SameSize) {
371 scoped_refptr<net::X509Certificate> certificate = ImportTestCert();
372 const std::string message =
373 CreateCertMessage(CreateCertMessageFromCert(*certificate));
374 base::ScopedClosureRunner reset_max =
375 SignedExchangeCertFetcher::SetMaxCertSizeForTest(message.size());
376
377 std::unique_ptr<SignedExchangeCertFetcher> fetcher =
378 CreateFetcherAndStart(url_, false /* force_fetch */);
379 CallOnReceiveResponse();
380 mojo::DataPipe data_pipe(message.size());
381 CHECK(mojo::BlockingCopyFromString(message, data_pipe.producer_handle));
382 data_pipe.producer_handle.reset();
383 mock_loader_factory_.client_remote()->OnStartLoadingResponseBody(
384 std::move(data_pipe.consumer_handle));
385 mock_loader_factory_.client_remote()->OnComplete(
386 network::URLLoaderCompletionStatus(net::OK));
387 RunUntilIdle();
388
389 EXPECT_TRUE(callback_called_);
390 EXPECT_EQ(SignedExchangeLoadResult::kSuccess, result_);
391 EXPECT_TRUE(cert_result_);
392 }
393
TEST_F(SignedExchangeCertFetcherTest,MaxCertSize_MultipleChunked)394 TEST_F(SignedExchangeCertFetcherTest, MaxCertSize_MultipleChunked) {
395 scoped_refptr<net::X509Certificate> certificate = ImportTestCert();
396 const std::string message =
397 CreateCertMessage(CreateCertMessageFromCert(*certificate));
398 base::ScopedClosureRunner reset_max =
399 SignedExchangeCertFetcher::SetMaxCertSizeForTest(message.size() - 1);
400
401 std::unique_ptr<SignedExchangeCertFetcher> fetcher =
402 CreateFetcherAndStart(url_, false /* force_fetch */);
403 CallOnReceiveResponse();
404 mojo::DataPipe data_pipe(message.size() / 2 + 1);
405 ASSERT_TRUE(mojo::BlockingCopyFromString(
406 message.substr(0, message.size() / 2), data_pipe.producer_handle));
407 mock_loader_factory_.client_remote()->OnStartLoadingResponseBody(
408 std::move(data_pipe.consumer_handle));
409 RunUntilIdle();
410 ASSERT_TRUE(mojo::BlockingCopyFromString(message.substr(message.size() / 2),
411 data_pipe.producer_handle));
412 data_pipe.producer_handle.reset();
413 mock_loader_factory_.client_remote()->OnComplete(
414 network::URLLoaderCompletionStatus(net::OK));
415 RunUntilIdle();
416
417 EXPECT_TRUE(callback_called_);
418 EXPECT_EQ(SignedExchangeLoadResult::kCertFetchError, result_);
419 EXPECT_FALSE(cert_result_);
420 }
421
TEST_F(SignedExchangeCertFetcherTest,MaxCertSize_ContentLengthCheck)422 TEST_F(SignedExchangeCertFetcherTest, MaxCertSize_ContentLengthCheck) {
423 scoped_refptr<net::X509Certificate> certificate = ImportTestCert();
424 const std::string message =
425 CreateCertMessage(CreateCertMessageFromCert(*certificate));
426 base::ScopedClosureRunner reset_max =
427 SignedExchangeCertFetcher::SetMaxCertSizeForTest(message.size() - 1);
428
429 std::unique_ptr<SignedExchangeCertFetcher> fetcher =
430 CreateFetcherAndStart(url_, false /* force_fetch */);
431 auto response_head = network::mojom::URLResponseHead::New();
432 response_head->headers =
433 base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK");
434 response_head->content_length = message.size();
435 mock_loader_factory_.client_remote()->OnReceiveResponse(
436 std::move(response_head));
437 mojo::DataPipe data_pipe(message.size());
438 CHECK(mojo::BlockingCopyFromString(message, data_pipe.producer_handle));
439 data_pipe.producer_handle.reset();
440 mock_loader_factory_.client_remote()->OnStartLoadingResponseBody(
441 std::move(data_pipe.consumer_handle));
442 mock_loader_factory_.client_remote()->OnComplete(
443 network::URLLoaderCompletionStatus(net::OK));
444 RunUntilIdle();
445
446 EXPECT_TRUE(callback_called_);
447 EXPECT_EQ(SignedExchangeLoadResult::kCertFetchError, result_);
448 EXPECT_FALSE(cert_result_);
449 }
450
TEST_F(SignedExchangeCertFetcherTest,Abort_Redirect)451 TEST_F(SignedExchangeCertFetcherTest, Abort_Redirect) {
452 std::unique_ptr<SignedExchangeCertFetcher> fetcher =
453 CreateFetcherAndStart(url_, false /* force_fetch */);
454 net::RedirectInfo redirect_info;
455 mock_loader_factory_.client_remote()->OnReceiveRedirect(
456 redirect_info, network::mojom::URLResponseHead::New());
457 RunUntilIdle();
458
459 EXPECT_TRUE(callback_called_);
460 EXPECT_EQ(SignedExchangeLoadResult::kCertFetchError, result_);
461 EXPECT_FALSE(cert_result_);
462 }
463
TEST_F(SignedExchangeCertFetcherTest,Abort_404)464 TEST_F(SignedExchangeCertFetcherTest, Abort_404) {
465 std::unique_ptr<SignedExchangeCertFetcher> fetcher =
466 CreateFetcherAndStart(url_, false /* force_fetch */);
467 auto response_head = network::mojom::URLResponseHead::New();
468 response_head->headers =
469 base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 404 Not Found");
470 mock_loader_factory_.client_remote()->OnReceiveResponse(
471 std::move(response_head));
472 RunUntilIdle();
473
474 EXPECT_TRUE(callback_called_);
475 EXPECT_EQ(SignedExchangeLoadResult::kCertFetchError, result_);
476 EXPECT_FALSE(cert_result_);
477 }
478
TEST_F(SignedExchangeCertFetcherTest,WrongMimeType)479 TEST_F(SignedExchangeCertFetcherTest, WrongMimeType) {
480 std::unique_ptr<SignedExchangeCertFetcher> fetcher =
481 CreateFetcherAndStart(url_, false /* force_fetch */);
482 auto response_head = network::mojom::URLResponseHead::New();
483 response_head->headers =
484 base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK");
485 response_head->headers->AddHeader("Content-Type: application/octet-stream");
486 response_head->mime_type = "application/octet-stream";
487 mock_loader_factory_.client_remote()->OnReceiveResponse(
488 std::move(response_head));
489 RunUntilIdle();
490
491 EXPECT_TRUE(callback_called_);
492 EXPECT_EQ(SignedExchangeLoadResult::kCertFetchError, result_);
493 EXPECT_FALSE(cert_result_);
494 }
495
TEST_F(SignedExchangeCertFetcherTest,Invalid_CertData)496 TEST_F(SignedExchangeCertFetcherTest, Invalid_CertData) {
497 std::unique_ptr<SignedExchangeCertFetcher> fetcher =
498 CreateFetcherAndStart(url_, false /* force_fetch */);
499 CallOnReceiveResponse();
500 const std::string message = CreateCertMessage("Invalid Cert Data");
501 mojo::DataPipe data_pipe(message.size());
502 CHECK(mojo::BlockingCopyFromString(message, data_pipe.producer_handle));
503 data_pipe.producer_handle.reset();
504 mock_loader_factory_.client_remote()->OnStartLoadingResponseBody(
505 std::move(data_pipe.consumer_handle));
506 mock_loader_factory_.client_remote()->OnComplete(
507 network::URLLoaderCompletionStatus(net::OK));
508 RunUntilIdle();
509
510 EXPECT_TRUE(callback_called_);
511 EXPECT_EQ(SignedExchangeLoadResult::kCertParseError, result_);
512 EXPECT_FALSE(cert_result_);
513 }
514
TEST_F(SignedExchangeCertFetcherTest,Invalid_CertMessage)515 TEST_F(SignedExchangeCertFetcherTest, Invalid_CertMessage) {
516 std::unique_ptr<SignedExchangeCertFetcher> fetcher =
517 CreateFetcherAndStart(url_, false /* force_fetch */);
518 CallOnReceiveResponse();
519
520 const std::string message = "Invalid cert message";
521
522 mojo::DataPipe data_pipe(message.size());
523 CHECK(mojo::BlockingCopyFromString(message, data_pipe.producer_handle));
524 data_pipe.producer_handle.reset();
525 mock_loader_factory_.client_remote()->OnStartLoadingResponseBody(
526 std::move(data_pipe.consumer_handle));
527
528 mock_loader_factory_.client_remote()->OnComplete(
529 network::URLLoaderCompletionStatus(net::OK));
530 RunUntilIdle();
531
532 EXPECT_TRUE(callback_called_);
533 EXPECT_EQ(SignedExchangeLoadResult::kCertParseError, result_);
534 EXPECT_FALSE(cert_result_);
535 }
536
TEST_F(SignedExchangeCertFetcherTest,Throttle_Simple)537 TEST_F(SignedExchangeCertFetcherTest, Throttle_Simple) {
538 DeferringURLLoaderThrottle* throttle = InitializeDeferringURLLoaderThrottle();
539 std::unique_ptr<SignedExchangeCertFetcher> fetcher =
540 CreateFetcherAndStart(url_, false /* force_fetch */);
541 RunUntilIdle();
542
543 EXPECT_TRUE(throttle->will_start_request_called());
544 EXPECT_FALSE(mock_loader_factory_.url_request());
545 EXPECT_FALSE(mock_loader_factory_.client_remote());
546
547 throttle->delegate()->Resume();
548
549 RunUntilIdle();
550
551 CallOnReceiveResponse();
552
553 RunUntilIdle();
554
555 EXPECT_TRUE(throttle->will_process_response_called());
556 mock_loader_factory_.client_remote()->OnStartLoadingResponseBody(
557 CreateTestDataFilledDataPipe());
558
559 mock_loader_factory_.client_remote()->OnComplete(
560 network::URLLoaderCompletionStatus(net::OK));
561 RunUntilIdle();
562
563 EXPECT_FALSE(callback_called_);
564
565 throttle->delegate()->Resume();
566 RunUntilIdle();
567
568 EXPECT_TRUE(callback_called_);
569 EXPECT_EQ(SignedExchangeLoadResult::kSuccess, result_);
570 ASSERT_TRUE(cert_result_);
571 EXPECT_EQ(GetTestDataCertFingerprint256(),
572 cert_result_->cert()->CalculateChainFingerprint256());
573 }
574
TEST_F(SignedExchangeCertFetcherTest,Throttle_AbortsOnRequest)575 TEST_F(SignedExchangeCertFetcherTest, Throttle_AbortsOnRequest) {
576 DeferringURLLoaderThrottle* throttle = InitializeDeferringURLLoaderThrottle();
577 std::unique_ptr<SignedExchangeCertFetcher> fetcher =
578 CreateFetcherAndStart(url_, false /* force_fetch */);
579 RunUntilIdle();
580
581 throttle->delegate()->CancelWithError(net::ERR_INVALID_SIGNED_EXCHANGE);
582
583 RunUntilIdle();
584
585 EXPECT_TRUE(callback_called_);
586 EXPECT_EQ(SignedExchangeLoadResult::kCertFetchError, result_);
587 EXPECT_FALSE(cert_result_);
588 }
589
TEST_F(SignedExchangeCertFetcherTest,Throttle_AbortsOnRedirect)590 TEST_F(SignedExchangeCertFetcherTest, Throttle_AbortsOnRedirect) {
591 DeferringURLLoaderThrottle* throttle = InitializeDeferringURLLoaderThrottle();
592 std::unique_ptr<SignedExchangeCertFetcher> fetcher =
593 CreateFetcherAndStart(url_, false /* force_fetch */);
594 RunUntilIdle();
595
596 throttle->delegate()->Resume();
597
598 RunUntilIdle();
599
600 net::RedirectInfo redirect_info;
601
602 mock_loader_factory_.client_remote()->OnReceiveRedirect(
603 redirect_info, network::mojom::URLResponseHead::New());
604 RunUntilIdle();
605
606 EXPECT_TRUE(throttle->will_redirect_request_called());
607
608 throttle->delegate()->CancelWithError(net::ERR_INVALID_SIGNED_EXCHANGE);
609 RunUntilIdle();
610
611 EXPECT_TRUE(callback_called_);
612 EXPECT_EQ(SignedExchangeLoadResult::kCertFetchError, result_);
613 EXPECT_FALSE(cert_result_);
614 }
615
TEST_F(SignedExchangeCertFetcherTest,Throttle_AbortsOnResponse)616 TEST_F(SignedExchangeCertFetcherTest, Throttle_AbortsOnResponse) {
617 DeferringURLLoaderThrottle* throttle = InitializeDeferringURLLoaderThrottle();
618 std::unique_ptr<SignedExchangeCertFetcher> fetcher =
619 CreateFetcherAndStart(url_, false /* force_fetch */);
620 RunUntilIdle();
621
622 throttle->delegate()->Resume();
623
624 RunUntilIdle();
625
626 CallOnReceiveResponse();
627
628 RunUntilIdle();
629
630 EXPECT_TRUE(throttle->will_process_response_called());
631
632 mock_loader_factory_.client_remote()->OnStartLoadingResponseBody(
633 CreateTestDataFilledDataPipe());
634
635 mock_loader_factory_.client_remote()->OnComplete(
636 network::URLLoaderCompletionStatus(net::OK));
637 RunUntilIdle();
638
639 EXPECT_FALSE(callback_called_);
640
641 throttle->delegate()->CancelWithError(net::ERR_INVALID_SIGNED_EXCHANGE);
642 RunUntilIdle();
643
644 EXPECT_TRUE(callback_called_);
645 EXPECT_EQ(SignedExchangeLoadResult::kCertFetchError, result_);
646 EXPECT_FALSE(cert_result_);
647 }
648
TEST_F(SignedExchangeCertFetcherTest,DeleteFetcher_BeforeReceiveResponse)649 TEST_F(SignedExchangeCertFetcherTest, DeleteFetcher_BeforeReceiveResponse) {
650 std::unique_ptr<SignedExchangeCertFetcher> fetcher =
651 CreateFetcherAndStart(url_, false /* force_fetch */);
652 RunUntilIdle();
653 fetcher.reset();
654 RunUntilIdle();
655
656 EXPECT_FALSE(callback_called_);
657 EXPECT_FALSE(cert_result_);
658 }
659
TEST_F(SignedExchangeCertFetcherTest,DeleteFetcher_BeforeResponseBody)660 TEST_F(SignedExchangeCertFetcherTest, DeleteFetcher_BeforeResponseBody) {
661 std::unique_ptr<SignedExchangeCertFetcher> fetcher =
662 CreateFetcherAndStart(url_, false /* force_fetch */);
663 CallOnReceiveResponse();
664 RunUntilIdle();
665 fetcher.reset();
666 RunUntilIdle();
667
668 EXPECT_FALSE(callback_called_);
669 EXPECT_FALSE(cert_result_);
670 }
671
TEST_F(SignedExchangeCertFetcherTest,DeleteFetcher_WhileReceivingBody)672 TEST_F(SignedExchangeCertFetcherTest, DeleteFetcher_WhileReceivingBody) {
673 std::unique_ptr<SignedExchangeCertFetcher> fetcher =
674 CreateFetcherAndStart(url_, false /* force_fetch */);
675 CallOnReceiveResponse();
676 scoped_refptr<net::X509Certificate> certificate = ImportTestCert();
677 const std::string message =
678 CreateCertMessage(CreateCertMessageFromCert(*certificate));
679 mojo::DataPipe data_pipe(message.size() / 2 + 1);
680 ASSERT_TRUE(mojo::BlockingCopyFromString(
681 message.substr(0, message.size() / 2), data_pipe.producer_handle));
682 mock_loader_factory_.client_remote()->OnStartLoadingResponseBody(
683 std::move(data_pipe.consumer_handle));
684 RunUntilIdle();
685 fetcher.reset();
686 RunUntilIdle();
687 ASSERT_TRUE(mojo::BlockingCopyFromString(message.substr(message.size() / 2),
688 data_pipe.producer_handle));
689 RunUntilIdle();
690
691 EXPECT_FALSE(callback_called_);
692 EXPECT_FALSE(cert_result_);
693 }
694
TEST_F(SignedExchangeCertFetcherTest,DeleteFetcher_AfterReceivingBody)695 TEST_F(SignedExchangeCertFetcherTest, DeleteFetcher_AfterReceivingBody) {
696 std::unique_ptr<SignedExchangeCertFetcher> fetcher =
697 CreateFetcherAndStart(url_, false /* force_fetch */);
698 CallOnReceiveResponse();
699 scoped_refptr<net::X509Certificate> certificate = ImportTestCert();
700 const std::string message =
701 CreateCertMessage(CreateCertMessageFromCert(*certificate));
702 mojo::DataPipe data_pipe(message.size());
703 CHECK(mojo::BlockingCopyFromString(message, data_pipe.producer_handle));
704 mock_loader_factory_.client_remote()->OnStartLoadingResponseBody(
705 std::move(data_pipe.consumer_handle));
706 RunUntilIdle();
707 CloseClientPipe();
708 RunUntilIdle();
709 data_pipe.producer_handle.reset();
710 fetcher.reset();
711 RunUntilIdle();
712
713 EXPECT_FALSE(callback_called_);
714 EXPECT_FALSE(cert_result_);
715 }
716
TEST_F(SignedExchangeCertFetcherTest,CloseClientPipe_BeforeReceiveResponse)717 TEST_F(SignedExchangeCertFetcherTest, CloseClientPipe_BeforeReceiveResponse) {
718 std::unique_ptr<SignedExchangeCertFetcher> fetcher =
719 CreateFetcherAndStart(url_, false /* force_fetch */);
720 RunUntilIdle();
721 CloseClientPipe();
722 RunUntilIdle();
723
724 EXPECT_TRUE(callback_called_);
725 EXPECT_EQ(SignedExchangeLoadResult::kCertFetchError, result_);
726 EXPECT_FALSE(cert_result_);
727 }
728
TEST_F(SignedExchangeCertFetcherTest,CloseClientPipe_BeforeResponseBody)729 TEST_F(SignedExchangeCertFetcherTest, CloseClientPipe_BeforeResponseBody) {
730 std::unique_ptr<SignedExchangeCertFetcher> fetcher =
731 CreateFetcherAndStart(url_, false /* force_fetch */);
732 CallOnReceiveResponse();
733 RunUntilIdle();
734 CloseClientPipe();
735 RunUntilIdle();
736
737 EXPECT_TRUE(callback_called_);
738 EXPECT_EQ(SignedExchangeLoadResult::kCertFetchError, result_);
739 EXPECT_FALSE(cert_result_);
740 }
741
TEST_F(SignedExchangeCertFetcherTest,CloseClientPipe_WhileReceivingBody)742 TEST_F(SignedExchangeCertFetcherTest, CloseClientPipe_WhileReceivingBody) {
743 std::unique_ptr<SignedExchangeCertFetcher> fetcher =
744 CreateFetcherAndStart(url_, false /* force_fetch */);
745 CallOnReceiveResponse();
746 scoped_refptr<net::X509Certificate> certificate = ImportTestCert();
747 const std::string message =
748 CreateCertMessage(CreateCertMessageFromCert(*certificate));
749 mojo::DataPipe data_pipe(message.size() / 2 + 1);
750 ASSERT_TRUE(mojo::BlockingCopyFromString(
751 message.substr(0, message.size() / 2), data_pipe.producer_handle));
752 mock_loader_factory_.client_remote()->OnStartLoadingResponseBody(
753 std::move(data_pipe.consumer_handle));
754 RunUntilIdle();
755 CloseClientPipe();
756 RunUntilIdle();
757 data_pipe.producer_handle.reset();
758 RunUntilIdle();
759 EXPECT_TRUE(callback_called_);
760 // SignedExchangeCertFetcher receives a truncated cert cbor.
761 EXPECT_EQ(SignedExchangeLoadResult::kCertParseError, result_);
762 EXPECT_FALSE(cert_result_);
763 }
764
TEST_F(SignedExchangeCertFetcherTest,CloseClientPipe_AfterReceivingBody)765 TEST_F(SignedExchangeCertFetcherTest, CloseClientPipe_AfterReceivingBody) {
766 std::unique_ptr<SignedExchangeCertFetcher> fetcher =
767 CreateFetcherAndStart(url_, false /* force_fetch */);
768 CallOnReceiveResponse();
769 scoped_refptr<net::X509Certificate> certificate = ImportTestCert();
770 const std::string message =
771 CreateCertMessage(CreateCertMessageFromCert(*certificate));
772 mojo::DataPipe data_pipe(message.size());
773 CHECK(mojo::BlockingCopyFromString(message, data_pipe.producer_handle));
774 mock_loader_factory_.client_remote()->OnStartLoadingResponseBody(
775 std::move(data_pipe.consumer_handle));
776 RunUntilIdle();
777 CloseClientPipe();
778 RunUntilIdle();
779 data_pipe.producer_handle.reset();
780 RunUntilIdle();
781
782 EXPECT_TRUE(callback_called_);
783 EXPECT_EQ(SignedExchangeLoadResult::kSuccess, result_);
784 ASSERT_TRUE(cert_result_);
785 EXPECT_EQ(certificate->CalculateChainFingerprint256(),
786 cert_result_->cert()->CalculateChainFingerprint256());
787 }
788
TEST_F(SignedExchangeCertFetcherTest,DataURL)789 TEST_F(SignedExchangeCertFetcherTest, DataURL) {
790 std::string data_url_string = "data:application/cert-chain+cbor";
791 std::string output;
792 base::Base64Encode(CreateTestData(), &output);
793 data_url_string += ";base64," + output;
794 const GURL data_url = GURL(data_url_string);
795 std::unique_ptr<SignedExchangeCertFetcher> fetcher =
796 CreateFetcherAndStart(data_url, false /* force_fetch */);
797
798 RunUntilIdle();
799 EXPECT_TRUE(callback_called_);
800 EXPECT_EQ(SignedExchangeLoadResult::kSuccess, result_);
801 ASSERT_TRUE(cert_result_);
802 EXPECT_EQ(GetTestDataCertFingerprint256(),
803 cert_result_->cert()->CalculateChainFingerprint256());
804 }
805
TEST_F(SignedExchangeCertFetcherTest,DataURLWithWrongMimeType)806 TEST_F(SignedExchangeCertFetcherTest, DataURLWithWrongMimeType) {
807 const GURL data_url = GURL("data:application/octet-stream,foobar");
808 std::unique_ptr<SignedExchangeCertFetcher> fetcher =
809 CreateFetcherAndStart(data_url, false /* force_fetch */);
810
811 RunUntilIdle();
812
813 EXPECT_TRUE(callback_called_);
814 EXPECT_EQ(SignedExchangeLoadResult::kCertFetchError, result_);
815 }
816
817 } // namespace content
818