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