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