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