blob: 82c8f35171a583b302dd28c63d06274a33206309 [file] [log] [blame]
[email protected]1bc6f5e2012-03-15 00:20:581// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]f61c3972010-12-23 09:54:152// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// This test suite uses SSLClientSocket to test the implementation of
6// SSLServerSocket. In order to establish connections between the sockets
7// we need two additional classes:
8// 1. FakeSocket
9// Connects SSL socket to FakeDataChannel. This class is just a stub.
10//
11// 2. FakeDataChannel
12// Implements the actual exchange of data between two FakeSockets.
13//
14// Implementations of these two classes are included in this file.
15
16#include "net/socket/ssl_server_socket.h"
17
tbansalf82cc8e2015-10-14 20:05:4918#include <stdint.h>
[email protected]55ee0e52011-07-21 18:29:4419#include <stdlib.h>
[email protected]f61c3972010-12-23 09:54:1520#include <queue>
dchengc7eeda422015-12-26 03:56:4821#include <utility>
[email protected]f61c3972010-12-23 09:54:1522
svaldez2135be52016-04-20 16:34:5323#include <openssl/evp.h>
24#include <openssl/ssl.h>
25#include <openssl/x509.h>
26
ryanchung987b2ff2016-02-19 00:17:1227#include "base/callback_helpers.h"
[email protected]55ee0e52011-07-21 18:29:4428#include "base/compiler_specific.h"
[email protected]57999812013-02-24 05:40:5229#include "base/files/file_path.h"
thestigd8df0332014-09-04 06:33:2930#include "base/files/file_util.h"
skyostil4891b25b2015-06-11 11:43:4531#include "base/location.h"
tbansalf82cc8e2015-10-14 20:05:4932#include "base/logging.h"
Avi Drissman13fc8932015-12-20 04:40:4633#include "base/macros.h"
[email protected]18b577412013-07-18 04:19:1534#include "base/message_loop/message_loop.h"
fdoray5eeb7642016-06-22 16:11:2835#include "base/run_loop.h"
skyostil4891b25b2015-06-11 11:43:4536#include "base/single_thread_task_runner.h"
gabf767595f2016-05-11 18:50:3537#include "base/threading/thread_task_runner_handle.h"
ryanchung987b2ff2016-02-19 00:17:1238#include "build/build_config.h"
[email protected]4b559b4d2011-04-14 17:37:1439#include "crypto/nss_util.h"
40#include "crypto/rsa_private_key.h"
ryanchung987b2ff2016-02-19 00:17:1241#include "crypto/signature_creator.h"
[email protected]f61c3972010-12-23 09:54:1542#include "net/base/address_list.h"
[email protected]6ea7b152011-12-21 21:21:1343#include "net/base/completion_callback.h"
[email protected]f61c3972010-12-23 09:54:1544#include "net/base/host_port_pair.h"
45#include "net/base/io_buffer.h"
martijna2e83bd2016-03-18 13:10:4546#include "net/base/ip_address.h"
[email protected]e7f74da2011-04-19 23:49:3547#include "net/base/ip_endpoint.h"
[email protected]f61c3972010-12-23 09:54:1548#include "net/base/net_errors.h"
[email protected]6e7845ae2013-03-29 21:48:1149#include "net/cert/cert_status_flags.h"
rsleevid6de8302016-06-21 01:33:2050#include "net/cert/ct_policy_enforcer.h"
51#include "net/cert/ct_policy_status.h"
52#include "net/cert/ct_verifier.h"
[email protected]6e7845ae2013-03-29 21:48:1153#include "net/cert/mock_cert_verifier.h"
ryanchung987b2ff2016-02-19 00:17:1254#include "net/cert/mock_client_cert_verifier.h"
eranmdcec9632016-10-10 14:16:1055#include "net/cert/signed_certificate_timestamp_and_status.h"
[email protected]6e7845ae2013-03-29 21:48:1156#include "net/cert/x509_certificate.h"
[email protected]b1c988b2013-06-13 06:48:1157#include "net/http/transport_security_state.h"
mikecironef22f9812016-10-04 03:40:1958#include "net/log/net_log_with_source.h"
[email protected]f61c3972010-12-23 09:54:1559#include "net/socket/client_socket_factory.h"
60#include "net/socket/socket_test_util.h"
61#include "net/socket/ssl_client_socket.h"
[email protected]3268023f2011-05-05 00:08:1062#include "net/socket/stream_socket.h"
ryanchung987b2ff2016-02-19 00:17:1263#include "net/ssl/ssl_cert_request_info.h"
davidben9dd84872015-05-02 00:22:5864#include "net/ssl/ssl_cipher_suite_names.h"
davidben9dd84872015-05-02 00:22:5865#include "net/ssl/ssl_connection_status_flags.h"
[email protected]536fd0b2013-03-14 17:41:5766#include "net/ssl/ssl_info.h"
ryanchung987b2ff2016-02-19 00:17:1267#include "net/ssl/ssl_private_key.h"
svaldez6e7e82a22015-10-28 19:39:5368#include "net/ssl/ssl_server_config.h"
ryanchung987b2ff2016-02-19 00:17:1269#include "net/ssl/test_ssl_private_key.h"
[email protected]6e7845ae2013-03-29 21:48:1170#include "net/test/cert_test_util.h"
robpercival214763f2016-07-01 23:27:0171#include "net/test/gtest_util.h"
rsleevia69c79a2016-06-22 03:28:4372#include "net/test/test_data_directory.h"
robpercival214763f2016-07-01 23:27:0173#include "testing/gmock/include/gmock/gmock.h"
[email protected]f61c3972010-12-23 09:54:1574#include "testing/gtest/include/gtest/gtest.h"
75#include "testing/platform_test.h"
76
robpercival214763f2016-07-01 23:27:0177using net::test::IsError;
78using net::test::IsOk;
79
[email protected]f61c3972010-12-23 09:54:1580namespace net {
81
82namespace {
83
ryanchung987b2ff2016-02-19 00:17:1284const char kClientCertFileName[] = "client_1.pem";
85const char kClientPrivateKeyFileName[] = "client_1.pk8";
86const char kWrongClientCertFileName[] = "client_2.pem";
87const char kWrongClientPrivateKeyFileName[] = "client_2.pk8";
88const char kClientCertCAFileName[] = "client_1_ca.pem";
89
rsleevid6de8302016-06-21 01:33:2090class MockCTVerifier : public CTVerifier {
91 public:
92 MockCTVerifier() = default;
93 ~MockCTVerifier() override = default;
94
95 int Verify(X509Certificate* cert,
96 const std::string& stapled_ocsp_response,
97 const std::string& sct_list_from_tls_extension,
eranmdcec9632016-10-10 14:16:1098 SignedCertificateTimestampAndStatusList* output_scts,
tfarina428341112016-09-22 13:38:2099 const NetLogWithSource& net_log) override {
rsleevid6de8302016-06-21 01:33:20100 return net::OK;
101 }
102
103 void SetObserver(Observer* observer) override {}
104};
105
106class MockCTPolicyEnforcer : public CTPolicyEnforcer {
107 public:
108 MockCTPolicyEnforcer() = default;
109 ~MockCTPolicyEnforcer() override = default;
110 ct::CertPolicyCompliance DoesConformToCertPolicy(
111 X509Certificate* cert,
112 const SCTList& verified_scts,
tfarina428341112016-09-22 13:38:20113 const NetLogWithSource& net_log) override {
rsleevid6de8302016-06-21 01:33:20114 return ct::CertPolicyCompliance::CERT_POLICY_COMPLIES_VIA_SCTS;
115 }
116
117 ct::EVPolicyCompliance DoesConformToCTEVPolicy(
118 X509Certificate* cert,
119 const ct::EVCertsWhitelist* ev_whitelist,
120 const SCTList& verified_scts,
tfarina428341112016-09-22 13:38:20121 const NetLogWithSource& net_log) override {
rsleevid6de8302016-06-21 01:33:20122 return ct::EVPolicyCompliance::EV_POLICY_COMPLIES_VIA_SCTS;
123 }
124};
125
[email protected]f61c3972010-12-23 09:54:15126class FakeDataChannel {
127 public:
[email protected]55ee0e52011-07-21 18:29:44128 FakeDataChannel()
[email protected]83039bb2011-12-09 18:43:55129 : read_buf_len_(0),
[email protected]c0e4dd12012-05-16 19:36:31130 closed_(false),
[email protected]d5492c52013-11-10 20:44:39131 write_called_after_close_(false),
132 weak_factory_(this) {
[email protected]f61c3972010-12-23 09:54:15133 }
134
[email protected]47a12862012-04-10 01:00:49135 int Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback) {
[email protected]4da82282014-07-16 18:40:43136 DCHECK(read_callback_.is_null());
dcheng08ea2af02014-08-25 23:38:09137 DCHECK(!read_buf_.get());
[email protected]c0e4dd12012-05-16 19:36:31138 if (closed_)
139 return 0;
[email protected]3f55aa12011-12-07 02:03:33140 if (data_.empty()) {
[email protected]f61c3972010-12-23 09:54:15141 read_callback_ = callback;
142 read_buf_ = buf;
143 read_buf_len_ = buf_len;
[email protected]fa6ce922014-07-17 04:27:04144 return ERR_IO_PENDING;
[email protected]f61c3972010-12-23 09:54:15145 }
tfarina9b6381442015-10-05 22:38:11146 return PropagateData(buf, buf_len);
[email protected]f61c3972010-12-23 09:54:15147 }
148
[email protected]47a12862012-04-10 01:00:49149 int Write(IOBuffer* buf, int buf_len, const CompletionCallback& callback) {
[email protected]4da82282014-07-16 18:40:43150 DCHECK(write_callback_.is_null());
[email protected]c0e4dd12012-05-16 19:36:31151 if (closed_) {
152 if (write_called_after_close_)
[email protected]fa6ce922014-07-17 04:27:04153 return ERR_CONNECTION_RESET;
[email protected]c0e4dd12012-05-16 19:36:31154 write_called_after_close_ = true;
155 write_callback_ = callback;
skyostil4891b25b2015-06-11 11:43:45156 base::ThreadTaskRunnerHandle::Get()->PostTask(
[email protected]c0e4dd12012-05-16 19:36:31157 FROM_HERE, base::Bind(&FakeDataChannel::DoWriteCallback,
158 weak_factory_.GetWeakPtr()));
[email protected]fa6ce922014-07-17 04:27:04159 return ERR_IO_PENDING;
[email protected]c0e4dd12012-05-16 19:36:31160 }
[email protected]4da82282014-07-16 18:40:43161 // This function returns synchronously, so make a copy of the buffer.
[email protected]fa6ce922014-07-17 04:27:04162 data_.push(new DrainableIOBuffer(
163 new StringIOBuffer(std::string(buf->data(), buf_len)),
[email protected]4da82282014-07-16 18:40:43164 buf_len));
skyostil4891b25b2015-06-11 11:43:45165 base::ThreadTaskRunnerHandle::Get()->PostTask(
[email protected]83039bb2011-12-09 18:43:55166 FROM_HERE, base::Bind(&FakeDataChannel::DoReadCallback,
167 weak_factory_.GetWeakPtr()));
[email protected]f61c3972010-12-23 09:54:15168 return buf_len;
169 }
170
[email protected]c0e4dd12012-05-16 19:36:31171 // Closes the FakeDataChannel. After Close() is called, Read() returns 0,
172 // indicating EOF, and Write() fails with ERR_CONNECTION_RESET. Note that
173 // after the FakeDataChannel is closed, the first Write() call completes
174 // asynchronously, which is necessary to reproduce bug 127822.
175 void Close() {
176 closed_ = true;
ryanchung987b2ff2016-02-19 00:17:12177 if (!read_callback_.is_null()) {
178 base::ThreadTaskRunnerHandle::Get()->PostTask(
179 FROM_HERE, base::Bind(&FakeDataChannel::DoReadCallback,
180 weak_factory_.GetWeakPtr()));
181 }
[email protected]c0e4dd12012-05-16 19:36:31182 }
183
[email protected]f61c3972010-12-23 09:54:15184 private:
185 void DoReadCallback() {
ryanchung987b2ff2016-02-19 00:17:12186 if (read_callback_.is_null())
187 return;
188
189 if (closed_) {
190 base::ResetAndReturn(&read_callback_).Run(ERR_CONNECTION_CLOSED);
191 return;
192 }
193
194 if (data_.empty())
[email protected]f61c3972010-12-23 09:54:15195 return;
196
tfarina9b6381442015-10-05 22:38:11197 int copied = PropagateData(read_buf_, read_buf_len_);
[email protected]83039bb2011-12-09 18:43:55198 CompletionCallback callback = read_callback_;
199 read_callback_.Reset();
200 read_buf_ = NULL;
201 read_buf_len_ = 0;
202 callback.Run(copied);
[email protected]f61c3972010-12-23 09:54:15203 }
204
[email protected]c0e4dd12012-05-16 19:36:31205 void DoWriteCallback() {
206 if (write_callback_.is_null())
207 return;
208
209 CompletionCallback callback = write_callback_;
210 write_callback_.Reset();
[email protected]fa6ce922014-07-17 04:27:04211 callback.Run(ERR_CONNECTION_RESET);
[email protected]c0e4dd12012-05-16 19:36:31212 }
213
tfarina9b6381442015-10-05 22:38:11214 int PropagateData(scoped_refptr<IOBuffer> read_buf, int read_buf_len) {
[email protected]fa6ce922014-07-17 04:27:04215 scoped_refptr<DrainableIOBuffer> buf = data_.front();
[email protected]f61c3972010-12-23 09:54:15216 int copied = std::min(buf->BytesRemaining(), read_buf_len);
217 memcpy(read_buf->data(), buf->data(), copied);
218 buf->DidConsume(copied);
219
220 if (!buf->BytesRemaining())
221 data_.pop();
222 return copied;
223 }
224
[email protected]83039bb2011-12-09 18:43:55225 CompletionCallback read_callback_;
[email protected]fa6ce922014-07-17 04:27:04226 scoped_refptr<IOBuffer> read_buf_;
[email protected]f61c3972010-12-23 09:54:15227 int read_buf_len_;
228
[email protected]c0e4dd12012-05-16 19:36:31229 CompletionCallback write_callback_;
230
[email protected]fa6ce922014-07-17 04:27:04231 std::queue<scoped_refptr<DrainableIOBuffer> > data_;
[email protected]f61c3972010-12-23 09:54:15232
[email protected]c0e4dd12012-05-16 19:36:31233 // True if Close() has been called.
234 bool closed_;
235
236 // Controls the completion of Write() after the FakeDataChannel is closed.
237 // After the FakeDataChannel is closed, the first Write() call completes
238 // asynchronously.
239 bool write_called_after_close_;
240
[email protected]d5492c52013-11-10 20:44:39241 base::WeakPtrFactory<FakeDataChannel> weak_factory_;
242
[email protected]f61c3972010-12-23 09:54:15243 DISALLOW_COPY_AND_ASSIGN(FakeDataChannel);
244};
245
[email protected]3268023f2011-05-05 00:08:10246class FakeSocket : public StreamSocket {
[email protected]f61c3972010-12-23 09:54:15247 public:
248 FakeSocket(FakeDataChannel* incoming_channel,
249 FakeDataChannel* outgoing_channel)
ryanchungeb9e3bc2016-03-08 05:08:10250 : incoming_(incoming_channel), outgoing_(outgoing_channel) {}
[email protected]f61c3972010-12-23 09:54:15251
dchengb03027d2014-10-21 12:00:20252 ~FakeSocket() override {}
[email protected]f61c3972010-12-23 09:54:15253
dchengb03027d2014-10-21 12:00:20254 int Read(IOBuffer* buf,
255 int buf_len,
256 const CompletionCallback& callback) override {
[email protected]3f55aa12011-12-07 02:03:33257 // Read random number of bytes.
258 buf_len = rand() % buf_len + 1;
259 return incoming_->Read(buf, buf_len, callback);
260 }
[email protected]f61c3972010-12-23 09:54:15261
dchengb03027d2014-10-21 12:00:20262 int Write(IOBuffer* buf,
263 int buf_len,
264 const CompletionCallback& callback) override {
[email protected]55ee0e52011-07-21 18:29:44265 // Write random number of bytes.
266 buf_len = rand() % buf_len + 1;
[email protected]f61c3972010-12-23 09:54:15267 return outgoing_->Write(buf, buf_len, callback);
268 }
269
Avi Drissman13fc8932015-12-20 04:40:46270 int SetReceiveBufferSize(int32_t size) override { return OK; }
[email protected]f61c3972010-12-23 09:54:15271
Avi Drissman13fc8932015-12-20 04:40:46272 int SetSendBufferSize(int32_t size) override { return OK; }
[email protected]f61c3972010-12-23 09:54:15273
dchengb03027d2014-10-21 12:00:20274 int Connect(const CompletionCallback& callback) override { return OK; }
[email protected]f61c3972010-12-23 09:54:15275
dchengb03027d2014-10-21 12:00:20276 void Disconnect() override {
[email protected]c0e4dd12012-05-16 19:36:31277 incoming_->Close();
278 outgoing_->Close();
279 }
[email protected]f61c3972010-12-23 09:54:15280
dchengb03027d2014-10-21 12:00:20281 bool IsConnected() const override { return true; }
[email protected]f61c3972010-12-23 09:54:15282
dchengb03027d2014-10-21 12:00:20283 bool IsConnectedAndIdle() const override { return true; }
[email protected]f61c3972010-12-23 09:54:15284
dchengb03027d2014-10-21 12:00:20285 int GetPeerAddress(IPEndPoint* address) const override {
martijna2e83bd2016-03-18 13:10:45286 *address = IPEndPoint(IPAddress::IPv4AllZeros(), 0 /*port*/);
[email protected]fa6ce922014-07-17 04:27:04287 return OK;
[email protected]f61c3972010-12-23 09:54:15288 }
289
dchengb03027d2014-10-21 12:00:20290 int GetLocalAddress(IPEndPoint* address) const override {
martijna2e83bd2016-03-18 13:10:45291 *address = IPEndPoint(IPAddress::IPv4AllZeros(), 0 /*port*/);
[email protected]fa6ce922014-07-17 04:27:04292 return OK;
[email protected]e7f74da2011-04-19 23:49:35293 }
294
tfarina428341112016-09-22 13:38:20295 const NetLogWithSource& NetLog() const override { return net_log_; }
[email protected]f61c3972010-12-23 09:54:15296
dchengb03027d2014-10-21 12:00:20297 void SetSubresourceSpeculation() override {}
298 void SetOmniboxSpeculation() override {}
[email protected]f61c3972010-12-23 09:54:15299
dchengb03027d2014-10-21 12:00:20300 bool WasEverUsed() const override { return true; }
[email protected]f61c3972010-12-23 09:54:15301
dchengb03027d2014-10-21 12:00:20302 bool WasNpnNegotiated() const override { return false; }
[email protected]5e6efa52011-06-27 17:26:41303
dchengb03027d2014-10-21 12:00:20304 NextProto GetNegotiatedProtocol() const override { return kProtoUnknown; }
[email protected]2d88e7d2012-07-19 17:55:17305
dchengb03027d2014-10-21 12:00:20306 bool GetSSLInfo(SSLInfo* ssl_info) override { return false; }
[email protected]2d88e7d2012-07-19 17:55:17307
ttuttle23fdb7b2015-05-15 01:28:03308 void GetConnectionAttempts(ConnectionAttempts* out) const override {
309 out->clear();
310 }
311
312 void ClearConnectionAttempts() override {}
313
314 void AddConnectionAttempts(const ConnectionAttempts& attempts) override {}
315
tbansalf82cc8e2015-10-14 20:05:49316 int64_t GetTotalReceivedBytes() const override {
317 NOTIMPLEMENTED();
318 return 0;
319 }
320
[email protected]f61c3972010-12-23 09:54:15321 private:
tfarina428341112016-09-22 13:38:20322 NetLogWithSource net_log_;
[email protected]f61c3972010-12-23 09:54:15323 FakeDataChannel* incoming_;
324 FakeDataChannel* outgoing_;
325
326 DISALLOW_COPY_AND_ASSIGN(FakeSocket);
327};
328
329} // namespace
330
331// Verify the correctness of the test helper classes first.
332TEST(FakeSocketTest, DataTransfer) {
333 // Establish channels between two sockets.
334 FakeDataChannel channel_1;
335 FakeDataChannel channel_2;
336 FakeSocket client(&channel_1, &channel_2);
337 FakeSocket server(&channel_2, &channel_1);
338
339 const char kTestData[] = "testing123";
340 const int kTestDataSize = strlen(kTestData);
341 const int kReadBufSize = 1024;
[email protected]fa6ce922014-07-17 04:27:04342 scoped_refptr<IOBuffer> write_buf = new StringIOBuffer(kTestData);
343 scoped_refptr<IOBuffer> read_buf = new IOBuffer(kReadBufSize);
[email protected]f61c3972010-12-23 09:54:15344
345 // Write then read.
[email protected]90499482013-06-01 00:39:50346 int written =
347 server.Write(write_buf.get(), kTestDataSize, CompletionCallback());
[email protected]55ee0e52011-07-21 18:29:44348 EXPECT_GT(written, 0);
349 EXPECT_LE(written, kTestDataSize);
350
[email protected]90499482013-06-01 00:39:50351 int read = client.Read(read_buf.get(), kReadBufSize, CompletionCallback());
[email protected]55ee0e52011-07-21 18:29:44352 EXPECT_GT(read, 0);
353 EXPECT_LE(read, written);
354 EXPECT_EQ(0, memcmp(kTestData, read_buf->data(), read));
[email protected]f61c3972010-12-23 09:54:15355
356 // Read then write.
[email protected]83039bb2011-12-09 18:43:55357 TestCompletionCallback callback;
[email protected]fa6ce922014-07-17 04:27:04358 EXPECT_EQ(ERR_IO_PENDING,
[email protected]90499482013-06-01 00:39:50359 server.Read(read_buf.get(), kReadBufSize, callback.callback()));
[email protected]55ee0e52011-07-21 18:29:44360
[email protected]90499482013-06-01 00:39:50361 written = client.Write(write_buf.get(), kTestDataSize, CompletionCallback());
[email protected]55ee0e52011-07-21 18:29:44362 EXPECT_GT(written, 0);
363 EXPECT_LE(written, kTestDataSize);
364
365 read = callback.WaitForResult();
366 EXPECT_GT(read, 0);
367 EXPECT_LE(read, written);
368 EXPECT_EQ(0, memcmp(kTestData, read_buf->data(), read));
[email protected]f61c3972010-12-23 09:54:15369}
370
371class SSLServerSocketTest : public PlatformTest {
372 public:
373 SSLServerSocketTest()
[email protected]fa6ce922014-07-17 04:27:04374 : socket_factory_(ClientSocketFactory::GetDefaultFactory()),
[email protected]b1c988b2013-06-13 06:48:11375 cert_verifier_(new MockCertVerifier()),
ryanchung987b2ff2016-02-19 00:17:12376 client_cert_verifier_(new MockClientCertVerifier()),
rsleevid6de8302016-06-21 01:33:20377 transport_security_state_(new TransportSecurityState),
378 ct_verifier_(new MockCTVerifier),
379 ct_policy_enforcer_(new MockCTPolicyEnforcer) {}
rsleevia5c430222016-03-11 05:55:12380
381 void SetUp() override {
382 PlatformTest::SetUp();
383
ryanchung987b2ff2016-02-19 00:17:12384 cert_verifier_->set_default_result(ERR_CERT_AUTHORITY_INVALID);
385 client_cert_verifier_->set_default_result(ERR_CERT_AUTHORITY_INVALID);
[email protected]f61c3972010-12-23 09:54:15386
ryanchungeb9e3bc2016-03-08 05:08:10387 server_cert_ =
388 ImportCertFromFile(GetTestCertsDirectory(), "unittest.selfsigned.der");
rsleevia5c430222016-03-11 05:55:12389 ASSERT_TRUE(server_cert_);
ryanchungeb9e3bc2016-03-08 05:08:10390 server_private_key_ = ReadTestKey("unittest.key.bin");
rsleevia5c430222016-03-11 05:55:12391 ASSERT_TRUE(server_private_key_);
[email protected]f61c3972010-12-23 09:54:15392
sergeyuff826d5e2015-05-13 20:35:22393 client_ssl_config_.false_start_enabled = false;
394 client_ssl_config_.channel_id_enabled = false;
[email protected]f61c3972010-12-23 09:54:15395
396 // Certificate provided by the host doesn't need authority.
rsleevi74e99742016-09-13 20:35:25397 client_ssl_config_.allowed_bad_certs.emplace_back(
398 server_cert_, CERT_STATUS_AUTHORITY_INVALID);
ryanchungeb9e3bc2016-03-08 05:08:10399 }
400
401 protected:
402 void CreateContext() {
403 client_socket_.reset();
404 server_socket_.reset();
405 channel_1_.reset();
406 channel_2_.reset();
407 server_context_.reset();
408 server_context_ = CreateSSLServerContext(
409 server_cert_.get(), *server_private_key_, server_ssl_config_);
410 }
411
412 void CreateSockets() {
413 client_socket_.reset();
414 server_socket_.reset();
415 channel_1_.reset(new FakeDataChannel());
416 channel_2_.reset(new FakeDataChannel());
danakj655b66c2016-04-16 00:51:38417 std::unique_ptr<ClientSocketHandle> client_connection(
418 new ClientSocketHandle);
419 client_connection->SetSocket(std::unique_ptr<StreamSocket>(
ryanchungeb9e3bc2016-03-08 05:08:10420 new FakeSocket(channel_1_.get(), channel_2_.get())));
danakj655b66c2016-04-16 00:51:38421 std::unique_ptr<StreamSocket> server_socket(
ryanchungeb9e3bc2016-03-08 05:08:10422 new FakeSocket(channel_2_.get(), channel_1_.get()));
[email protected]f61c3972010-12-23 09:54:15423
[email protected]fa6ce922014-07-17 04:27:04424 HostPortPair host_and_pair("unittest", 0);
425 SSLClientSocketContext context;
[email protected]9f59fac2012-03-21 23:18:11426 context.cert_verifier = cert_verifier_.get();
[email protected]b1c988b2013-06-13 06:48:11427 context.transport_security_state = transport_security_state_.get();
rsleevid6de8302016-06-21 01:33:20428 context.cert_transparency_verifier = ct_verifier_.get();
429 context.ct_policy_enforcer = ct_policy_enforcer_.get();
rsleevia5c430222016-03-11 05:55:12430
sergeyuff826d5e2015-05-13 20:35:22431 client_socket_ = socket_factory_->CreateSSLClientSocket(
dchengc7eeda422015-12-26 03:56:48432 std::move(client_connection), host_and_pair, client_ssl_config_,
433 context);
rsleevia5c430222016-03-11 05:55:12434 ASSERT_TRUE(client_socket_);
ryanchungeb9e3bc2016-03-08 05:08:10435
ryanchung987b2ff2016-02-19 00:17:12436 server_socket_ =
ryanchungeb9e3bc2016-03-08 05:08:10437 server_context_->CreateSSLServerSocket(std::move(server_socket));
rsleevia5c430222016-03-11 05:55:12438 ASSERT_TRUE(server_socket_);
[email protected]f61c3972010-12-23 09:54:15439 }
440
ryanchung987b2ff2016-02-19 00:17:12441 void ConfigureClientCertsForClient(const char* cert_file_name,
442 const char* private_key_file_name) {
443 client_ssl_config_.send_client_cert = true;
444 client_ssl_config_.client_cert =
445 ImportCertFromFile(GetTestCertsDirectory(), cert_file_name);
446 ASSERT_TRUE(client_ssl_config_.client_cert);
rsleevia5c430222016-03-11 05:55:12447
danakj655b66c2016-04-16 00:51:38448 std::unique_ptr<crypto::RSAPrivateKey> key =
449 ReadTestKey(private_key_file_name);
ryanchung987b2ff2016-02-19 00:17:12450 ASSERT_TRUE(key);
rsleevia5c430222016-03-11 05:55:12451
agl5a7cadf2016-07-13 16:52:53452 EVP_PKEY_up_ref(key->key());
453 client_ssl_config_.client_private_key =
davidbend80c12c2016-10-11 00:13:49454 WrapOpenSSLPrivateKey(bssl::UniquePtr<EVP_PKEY>(key->key()));
ryanchung987b2ff2016-02-19 00:17:12455 }
456
457 void ConfigureClientCertsForServer() {
458 server_ssl_config_.client_cert_type =
459 SSLServerConfig::ClientCertType::REQUIRE_CLIENT_CERT;
460
davidbend80c12c2016-10-11 00:13:49461 bssl::UniquePtr<STACK_OF(X509_NAME)> cert_names(
ryanchung987b2ff2016-02-19 00:17:12462 SSL_load_client_CA_file(GetTestCertsDirectory()
463 .AppendASCII(kClientCertCAFileName)
464 .MaybeAsASCII()
465 .c_str()));
466 ASSERT_TRUE(cert_names);
rsleevia5c430222016-03-11 05:55:12467
ryanchung987b2ff2016-02-19 00:17:12468 for (size_t i = 0; i < sk_X509_NAME_num(cert_names.get()); ++i) {
469 uint8_t* str = nullptr;
470 int length = i2d_X509_NAME(sk_X509_NAME_value(cert_names.get(), i), &str);
rsleevia5c430222016-03-11 05:55:12471 ASSERT_LT(0, length);
472
ryanchung987b2ff2016-02-19 00:17:12473 server_ssl_config_.cert_authorities_.push_back(std::string(
474 reinterpret_cast<const char*>(str), static_cast<size_t>(length)));
475 OPENSSL_free(str);
476 }
477
478 scoped_refptr<X509Certificate> expected_client_cert(
479 ImportCertFromFile(GetTestCertsDirectory(), kClientCertFileName));
rsleevia5c430222016-03-11 05:55:12480 ASSERT_TRUE(expected_client_cert);
481
ryanchung987b2ff2016-02-19 00:17:12482 client_cert_verifier_->AddResultForCert(expected_client_cert.get(), OK);
483
484 server_ssl_config_.client_cert_verifier = client_cert_verifier_.get();
485 }
486
danakj655b66c2016-04-16 00:51:38487 std::unique_ptr<crypto::RSAPrivateKey> ReadTestKey(
488 const base::StringPiece& name) {
ryanchung987b2ff2016-02-19 00:17:12489 base::FilePath certs_dir(GetTestCertsDirectory());
490 base::FilePath key_path = certs_dir.AppendASCII(name);
491 std::string key_string;
492 if (!base::ReadFileToString(key_path, &key_string))
493 return nullptr;
494 std::vector<uint8_t> key_vector(
495 reinterpret_cast<const uint8_t*>(key_string.data()),
496 reinterpret_cast<const uint8_t*>(key_string.data() +
497 key_string.length()));
danakj655b66c2016-04-16 00:51:38498 std::unique_ptr<crypto::RSAPrivateKey> key(
ryanchung987b2ff2016-02-19 00:17:12499 crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_vector));
500 return key;
501 }
ryanchung987b2ff2016-02-19 00:17:12502
danakj655b66c2016-04-16 00:51:38503 std::unique_ptr<FakeDataChannel> channel_1_;
504 std::unique_ptr<FakeDataChannel> channel_2_;
sergeyuff826d5e2015-05-13 20:35:22505 SSLConfig client_ssl_config_;
svaldez6e7e82a22015-10-28 19:39:53506 SSLServerConfig server_ssl_config_;
danakj655b66c2016-04-16 00:51:38507 std::unique_ptr<SSLClientSocket> client_socket_;
508 std::unique_ptr<SSLServerSocket> server_socket_;
[email protected]fa6ce922014-07-17 04:27:04509 ClientSocketFactory* socket_factory_;
danakj655b66c2016-04-16 00:51:38510 std::unique_ptr<MockCertVerifier> cert_verifier_;
511 std::unique_ptr<MockClientCertVerifier> client_cert_verifier_;
512 std::unique_ptr<TransportSecurityState> transport_security_state_;
rsleevid6de8302016-06-21 01:33:20513 std::unique_ptr<MockCTVerifier> ct_verifier_;
514 std::unique_ptr<MockCTPolicyEnforcer> ct_policy_enforcer_;
danakj655b66c2016-04-16 00:51:38515 std::unique_ptr<SSLServerContext> server_context_;
516 std::unique_ptr<crypto::RSAPrivateKey> server_private_key_;
ryanchungeb9e3bc2016-03-08 05:08:10517 scoped_refptr<X509Certificate> server_cert_;
[email protected]f61c3972010-12-23 09:54:15518};
519
[email protected]f61c3972010-12-23 09:54:15520// This test only executes creation of client and server sockets. This is to
521// test that creation of sockets doesn't crash and have minimal code to run
522// under valgrind in order to help debugging memory problems.
523TEST_F(SSLServerSocketTest, Initialize) {
rsleevia5c430222016-03-11 05:55:12524 ASSERT_NO_FATAL_FAILURE(CreateContext());
525 ASSERT_NO_FATAL_FAILURE(CreateSockets());
[email protected]f61c3972010-12-23 09:54:15526}
527
[email protected]a7ac3c32011-06-17 19:10:15528// This test executes Connect() on SSLClientSocket and Handshake() on
529// SSLServerSocket to make sure handshaking between the two sockets is
[email protected]f61c3972010-12-23 09:54:15530// completed successfully.
531TEST_F(SSLServerSocketTest, Handshake) {
rsleevia5c430222016-03-11 05:55:12532 ASSERT_NO_FATAL_FAILURE(CreateContext());
533 ASSERT_NO_FATAL_FAILURE(CreateSockets());
[email protected]f61c3972010-12-23 09:54:15534
[email protected]6ea7b152011-12-21 21:21:13535 TestCompletionCallback handshake_callback;
[email protected]6ea7b152011-12-21 21:21:13536 int server_ret = server_socket_->Handshake(handshake_callback.callback());
[email protected]f61c3972010-12-23 09:54:15537
ryanchung987b2ff2016-02-19 00:17:12538 TestCompletionCallback connect_callback;
[email protected]83039bb2011-12-09 18:43:55539 int client_ret = client_socket_->Connect(connect_callback.callback());
[email protected]f61c3972010-12-23 09:54:15540
ryanchung987b2ff2016-02-19 00:17:12541 client_ret = connect_callback.GetResult(client_ret);
542 server_ret = handshake_callback.GetResult(server_ret);
543
robpercival214763f2016-07-01 23:27:01544 ASSERT_THAT(client_ret, IsOk());
545 ASSERT_THAT(server_ret, IsOk());
[email protected]4dc832e2011-04-28 22:04:24546
547 // Make sure the cert status is expected.
548 SSLInfo ssl_info;
davidben9dd84872015-05-02 00:22:58549 ASSERT_TRUE(client_socket_->GetSSLInfo(&ssl_info));
[email protected]4dc832e2011-04-28 22:04:24550 EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, ssl_info.cert_status);
davidben9dd84872015-05-02 00:22:58551
552 // The default cipher suite should be ECDHE and, unless on NSS and the
553 // platform doesn't support it, an AEAD.
554 uint16_t cipher_suite =
555 SSLConnectionStatusToCipherSuite(ssl_info.connection_status);
556 const char* key_exchange;
557 const char* cipher;
558 const char* mac;
559 bool is_aead;
560 SSLCipherSuiteToStrings(&key_exchange, &cipher, &mac, &is_aead, cipher_suite);
561 EXPECT_STREQ("ECDHE_RSA", key_exchange);
davidben6cacd572015-09-29 22:24:10562 EXPECT_TRUE(is_aead);
[email protected]f61c3972010-12-23 09:54:15563}
564
ryanchungeb9e3bc2016-03-08 05:08:10565// This test makes sure the session cache is working.
566TEST_F(SSLServerSocketTest, HandshakeCached) {
rsleevia5c430222016-03-11 05:55:12567 ASSERT_NO_FATAL_FAILURE(CreateContext());
568 ASSERT_NO_FATAL_FAILURE(CreateSockets());
ryanchungeb9e3bc2016-03-08 05:08:10569
570 TestCompletionCallback handshake_callback;
571 int server_ret = server_socket_->Handshake(handshake_callback.callback());
572
573 TestCompletionCallback connect_callback;
574 int client_ret = client_socket_->Connect(connect_callback.callback());
575
576 client_ret = connect_callback.GetResult(client_ret);
577 server_ret = handshake_callback.GetResult(server_ret);
578
robpercival214763f2016-07-01 23:27:01579 ASSERT_THAT(client_ret, IsOk());
580 ASSERT_THAT(server_ret, IsOk());
ryanchungeb9e3bc2016-03-08 05:08:10581
582 // Make sure the cert status is expected.
583 SSLInfo ssl_info;
584 ASSERT_TRUE(client_socket_->GetSSLInfo(&ssl_info));
585 EXPECT_EQ(ssl_info.handshake_type, SSLInfo::HANDSHAKE_FULL);
586 SSLInfo ssl_server_info;
587 ASSERT_TRUE(server_socket_->GetSSLInfo(&ssl_server_info));
588 EXPECT_EQ(ssl_server_info.handshake_type, SSLInfo::HANDSHAKE_FULL);
589
590 // Make sure the second connection is cached.
rsleevia5c430222016-03-11 05:55:12591 ASSERT_NO_FATAL_FAILURE(CreateSockets());
ryanchungeb9e3bc2016-03-08 05:08:10592 TestCompletionCallback handshake_callback2;
593 int server_ret2 = server_socket_->Handshake(handshake_callback2.callback());
594
595 TestCompletionCallback connect_callback2;
596 int client_ret2 = client_socket_->Connect(connect_callback2.callback());
597
598 client_ret2 = connect_callback2.GetResult(client_ret2);
599 server_ret2 = handshake_callback2.GetResult(server_ret2);
600
robpercival214763f2016-07-01 23:27:01601 ASSERT_THAT(client_ret2, IsOk());
602 ASSERT_THAT(server_ret2, IsOk());
ryanchungeb9e3bc2016-03-08 05:08:10603
604 // Make sure the cert status is expected.
605 SSLInfo ssl_info2;
606 ASSERT_TRUE(client_socket_->GetSSLInfo(&ssl_info2));
607 EXPECT_EQ(ssl_info2.handshake_type, SSLInfo::HANDSHAKE_RESUME);
608 SSLInfo ssl_server_info2;
609 ASSERT_TRUE(server_socket_->GetSSLInfo(&ssl_server_info2));
610 EXPECT_EQ(ssl_server_info2.handshake_type, SSLInfo::HANDSHAKE_RESUME);
611}
612
613// This test makes sure the session cache separates out by server context.
614TEST_F(SSLServerSocketTest, HandshakeCachedContextSwitch) {
rsleevia5c430222016-03-11 05:55:12615 ASSERT_NO_FATAL_FAILURE(CreateContext());
616 ASSERT_NO_FATAL_FAILURE(CreateSockets());
ryanchungeb9e3bc2016-03-08 05:08:10617
618 TestCompletionCallback handshake_callback;
619 int server_ret = server_socket_->Handshake(handshake_callback.callback());
620
621 TestCompletionCallback connect_callback;
622 int client_ret = client_socket_->Connect(connect_callback.callback());
623
624 client_ret = connect_callback.GetResult(client_ret);
625 server_ret = handshake_callback.GetResult(server_ret);
626
robpercival214763f2016-07-01 23:27:01627 ASSERT_THAT(client_ret, IsOk());
628 ASSERT_THAT(server_ret, IsOk());
ryanchungeb9e3bc2016-03-08 05:08:10629
630 // Make sure the cert status is expected.
631 SSLInfo ssl_info;
632 ASSERT_TRUE(client_socket_->GetSSLInfo(&ssl_info));
633 EXPECT_EQ(ssl_info.handshake_type, SSLInfo::HANDSHAKE_FULL);
634 SSLInfo ssl_server_info;
635 ASSERT_TRUE(server_socket_->GetSSLInfo(&ssl_server_info));
636 EXPECT_EQ(ssl_server_info.handshake_type, SSLInfo::HANDSHAKE_FULL);
637
638 // Make sure the second connection is NOT cached when using a new context.
rsleevia5c430222016-03-11 05:55:12639 ASSERT_NO_FATAL_FAILURE(CreateContext());
640 ASSERT_NO_FATAL_FAILURE(CreateSockets());
ryanchungeb9e3bc2016-03-08 05:08:10641
642 TestCompletionCallback handshake_callback2;
643 int server_ret2 = server_socket_->Handshake(handshake_callback2.callback());
644
645 TestCompletionCallback connect_callback2;
646 int client_ret2 = client_socket_->Connect(connect_callback2.callback());
647
648 client_ret2 = connect_callback2.GetResult(client_ret2);
649 server_ret2 = handshake_callback2.GetResult(server_ret2);
650
robpercival214763f2016-07-01 23:27:01651 ASSERT_THAT(client_ret2, IsOk());
652 ASSERT_THAT(server_ret2, IsOk());
ryanchungeb9e3bc2016-03-08 05:08:10653
654 // Make sure the cert status is expected.
655 SSLInfo ssl_info2;
656 ASSERT_TRUE(client_socket_->GetSSLInfo(&ssl_info2));
657 EXPECT_EQ(ssl_info2.handshake_type, SSLInfo::HANDSHAKE_FULL);
658 SSLInfo ssl_server_info2;
659 ASSERT_TRUE(server_socket_->GetSSLInfo(&ssl_server_info2));
660 EXPECT_EQ(ssl_server_info2.handshake_type, SSLInfo::HANDSHAKE_FULL);
661}
662
ryanchung987b2ff2016-02-19 00:17:12663// This test executes Connect() on SSLClientSocket and Handshake() on
664// SSLServerSocket to make sure handshaking between the two sockets is
665// completed successfully, using client certificate.
666TEST_F(SSLServerSocketTest, HandshakeWithClientCert) {
667 scoped_refptr<X509Certificate> client_cert =
668 ImportCertFromFile(GetTestCertsDirectory(), kClientCertFileName);
rsleevia5c430222016-03-11 05:55:12669 ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForClient(
670 kClientCertFileName, kClientPrivateKeyFileName));
671 ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForServer());
672 ASSERT_NO_FATAL_FAILURE(CreateContext());
673 ASSERT_NO_FATAL_FAILURE(CreateSockets());
ryanchung987b2ff2016-02-19 00:17:12674
675 TestCompletionCallback handshake_callback;
676 int server_ret = server_socket_->Handshake(handshake_callback.callback());
677
678 TestCompletionCallback connect_callback;
679 int client_ret = client_socket_->Connect(connect_callback.callback());
680
681 client_ret = connect_callback.GetResult(client_ret);
682 server_ret = handshake_callback.GetResult(server_ret);
683
robpercival214763f2016-07-01 23:27:01684 ASSERT_THAT(client_ret, IsOk());
685 ASSERT_THAT(server_ret, IsOk());
ryanchung987b2ff2016-02-19 00:17:12686
687 // Make sure the cert status is expected.
688 SSLInfo ssl_info;
689 client_socket_->GetSSLInfo(&ssl_info);
690 EXPECT_EQ(CERT_STATUS_AUTHORITY_INVALID, ssl_info.cert_status);
691 server_socket_->GetSSLInfo(&ssl_info);
rsleevia5c430222016-03-11 05:55:12692 ASSERT_TRUE(ssl_info.cert.get());
ryanchung987b2ff2016-02-19 00:17:12693 EXPECT_TRUE(client_cert->Equals(ssl_info.cert.get()));
694}
695
ryanchungeb9e3bc2016-03-08 05:08:10696// This test executes Connect() on SSLClientSocket and Handshake() twice on
697// SSLServerSocket to make sure handshaking between the two sockets is
698// completed successfully, using client certificate. The second connection is
699// expected to succeed through the session cache.
700TEST_F(SSLServerSocketTest, HandshakeWithClientCertCached) {
701 scoped_refptr<X509Certificate> client_cert =
702 ImportCertFromFile(GetTestCertsDirectory(), kClientCertFileName);
rsleevia5c430222016-03-11 05:55:12703 ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForClient(
704 kClientCertFileName, kClientPrivateKeyFileName));
705 ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForServer());
706 ASSERT_NO_FATAL_FAILURE(CreateContext());
707 ASSERT_NO_FATAL_FAILURE(CreateSockets());
ryanchungeb9e3bc2016-03-08 05:08:10708
709 TestCompletionCallback handshake_callback;
710 int server_ret = server_socket_->Handshake(handshake_callback.callback());
711
712 TestCompletionCallback connect_callback;
713 int client_ret = client_socket_->Connect(connect_callback.callback());
714
715 client_ret = connect_callback.GetResult(client_ret);
716 server_ret = handshake_callback.GetResult(server_ret);
717
robpercival214763f2016-07-01 23:27:01718 ASSERT_THAT(client_ret, IsOk());
719 ASSERT_THAT(server_ret, IsOk());
ryanchungeb9e3bc2016-03-08 05:08:10720
721 // Make sure the cert status is expected.
722 SSLInfo ssl_info;
723 ASSERT_TRUE(client_socket_->GetSSLInfo(&ssl_info));
724 EXPECT_EQ(ssl_info.handshake_type, SSLInfo::HANDSHAKE_FULL);
725 SSLInfo ssl_server_info;
726 ASSERT_TRUE(server_socket_->GetSSLInfo(&ssl_server_info));
727 ASSERT_TRUE(ssl_server_info.cert.get());
728 EXPECT_TRUE(client_cert->Equals(ssl_server_info.cert.get()));
729 EXPECT_EQ(ssl_server_info.handshake_type, SSLInfo::HANDSHAKE_FULL);
730 server_socket_->Disconnect();
731 client_socket_->Disconnect();
732
733 // Create the connection again.
rsleevia5c430222016-03-11 05:55:12734 ASSERT_NO_FATAL_FAILURE(CreateSockets());
ryanchungeb9e3bc2016-03-08 05:08:10735 TestCompletionCallback handshake_callback2;
736 int server_ret2 = server_socket_->Handshake(handshake_callback2.callback());
737
738 TestCompletionCallback connect_callback2;
739 int client_ret2 = client_socket_->Connect(connect_callback2.callback());
740
741 client_ret2 = connect_callback2.GetResult(client_ret2);
742 server_ret2 = handshake_callback2.GetResult(server_ret2);
743
robpercival214763f2016-07-01 23:27:01744 ASSERT_THAT(client_ret2, IsOk());
745 ASSERT_THAT(server_ret2, IsOk());
ryanchungeb9e3bc2016-03-08 05:08:10746
747 // Make sure the cert status is expected.
748 SSLInfo ssl_info2;
749 ASSERT_TRUE(client_socket_->GetSSLInfo(&ssl_info2));
750 EXPECT_EQ(ssl_info2.handshake_type, SSLInfo::HANDSHAKE_RESUME);
751 SSLInfo ssl_server_info2;
752 ASSERT_TRUE(server_socket_->GetSSLInfo(&ssl_server_info2));
753 ASSERT_TRUE(ssl_server_info2.cert.get());
754 EXPECT_TRUE(client_cert->Equals(ssl_server_info2.cert.get()));
755 EXPECT_EQ(ssl_server_info2.handshake_type, SSLInfo::HANDSHAKE_RESUME);
756}
757
ryanchung987b2ff2016-02-19 00:17:12758TEST_F(SSLServerSocketTest, HandshakeWithClientCertRequiredNotSupplied) {
rsleevia5c430222016-03-11 05:55:12759 ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForServer());
760 ASSERT_NO_FATAL_FAILURE(CreateContext());
761 ASSERT_NO_FATAL_FAILURE(CreateSockets());
ryanchung987b2ff2016-02-19 00:17:12762 // Use the default setting for the client socket, which is to not send
763 // a client certificate. This will cause the client to receive an
764 // ERR_SSL_CLIENT_AUTH_CERT_NEEDED error, and allow for inspecting the
765 // requested cert_authorities from the CertificateRequest sent by the
766 // server.
767
768 TestCompletionCallback handshake_callback;
769 int server_ret = server_socket_->Handshake(handshake_callback.callback());
770
771 TestCompletionCallback connect_callback;
772 EXPECT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED,
773 connect_callback.GetResult(
774 client_socket_->Connect(connect_callback.callback())));
775
776 scoped_refptr<SSLCertRequestInfo> request_info = new SSLCertRequestInfo();
777 client_socket_->GetSSLCertRequestInfo(request_info.get());
778
779 // Check that the authority name that arrived in the CertificateRequest
780 // handshake message is as expected.
781 scoped_refptr<X509Certificate> client_cert =
782 ImportCertFromFile(GetTestCertsDirectory(), kClientCertFileName);
rsleevia5c430222016-03-11 05:55:12783 ASSERT_TRUE(client_cert);
ryanchung987b2ff2016-02-19 00:17:12784 EXPECT_TRUE(client_cert->IsIssuedByEncoded(request_info->cert_authorities));
785
786 client_socket_->Disconnect();
787
robpercival214763f2016-07-01 23:27:01788 EXPECT_THAT(handshake_callback.GetResult(server_ret), IsError(ERR_FAILED));
ryanchung987b2ff2016-02-19 00:17:12789}
790
ryanchungeb9e3bc2016-03-08 05:08:10791TEST_F(SSLServerSocketTest, HandshakeWithClientCertRequiredNotSuppliedCached) {
rsleevia5c430222016-03-11 05:55:12792 ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForServer());
793 ASSERT_NO_FATAL_FAILURE(CreateContext());
794 ASSERT_NO_FATAL_FAILURE(CreateSockets());
ryanchungeb9e3bc2016-03-08 05:08:10795 // Use the default setting for the client socket, which is to not send
796 // a client certificate. This will cause the client to receive an
797 // ERR_SSL_CLIENT_AUTH_CERT_NEEDED error, and allow for inspecting the
798 // requested cert_authorities from the CertificateRequest sent by the
799 // server.
800
801 TestCompletionCallback handshake_callback;
802 int server_ret = server_socket_->Handshake(handshake_callback.callback());
803
804 TestCompletionCallback connect_callback;
805 EXPECT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED,
806 connect_callback.GetResult(
807 client_socket_->Connect(connect_callback.callback())));
808
809 scoped_refptr<SSLCertRequestInfo> request_info = new SSLCertRequestInfo();
810 client_socket_->GetSSLCertRequestInfo(request_info.get());
811
812 // Check that the authority name that arrived in the CertificateRequest
813 // handshake message is as expected.
814 scoped_refptr<X509Certificate> client_cert =
815 ImportCertFromFile(GetTestCertsDirectory(), kClientCertFileName);
rsleevia5c430222016-03-11 05:55:12816 ASSERT_TRUE(client_cert);
ryanchungeb9e3bc2016-03-08 05:08:10817 EXPECT_TRUE(client_cert->IsIssuedByEncoded(request_info->cert_authorities));
818
819 client_socket_->Disconnect();
820
robpercival214763f2016-07-01 23:27:01821 EXPECT_THAT(handshake_callback.GetResult(server_ret), IsError(ERR_FAILED));
ryanchungeb9e3bc2016-03-08 05:08:10822 server_socket_->Disconnect();
823
824 // Below, check that the cache didn't store the result of a failed handshake.
rsleevia5c430222016-03-11 05:55:12825 ASSERT_NO_FATAL_FAILURE(CreateSockets());
ryanchungeb9e3bc2016-03-08 05:08:10826 TestCompletionCallback handshake_callback2;
827 int server_ret2 = server_socket_->Handshake(handshake_callback2.callback());
828
829 TestCompletionCallback connect_callback2;
830 EXPECT_EQ(ERR_SSL_CLIENT_AUTH_CERT_NEEDED,
831 connect_callback2.GetResult(
832 client_socket_->Connect(connect_callback2.callback())));
833
834 scoped_refptr<SSLCertRequestInfo> request_info2 = new SSLCertRequestInfo();
835 client_socket_->GetSSLCertRequestInfo(request_info2.get());
836
837 // Check that the authority name that arrived in the CertificateRequest
838 // handshake message is as expected.
839 EXPECT_TRUE(client_cert->IsIssuedByEncoded(request_info2->cert_authorities));
840
841 client_socket_->Disconnect();
842
robpercival214763f2016-07-01 23:27:01843 EXPECT_THAT(handshake_callback2.GetResult(server_ret2), IsError(ERR_FAILED));
ryanchungeb9e3bc2016-03-08 05:08:10844}
845
ryanchung987b2ff2016-02-19 00:17:12846TEST_F(SSLServerSocketTest, HandshakeWithWrongClientCertSupplied) {
847 scoped_refptr<X509Certificate> client_cert =
848 ImportCertFromFile(GetTestCertsDirectory(), kClientCertFileName);
rsleevia5c430222016-03-11 05:55:12849 ASSERT_TRUE(client_cert);
850
851 ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForClient(
852 kWrongClientCertFileName, kWrongClientPrivateKeyFileName));
853 ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForServer());
854 ASSERT_NO_FATAL_FAILURE(CreateContext());
855 ASSERT_NO_FATAL_FAILURE(CreateSockets());
ryanchung987b2ff2016-02-19 00:17:12856
857 TestCompletionCallback handshake_callback;
858 int server_ret = server_socket_->Handshake(handshake_callback.callback());
859
860 TestCompletionCallback connect_callback;
861 int client_ret = client_socket_->Connect(connect_callback.callback());
862
863 EXPECT_EQ(ERR_BAD_SSL_CLIENT_AUTH_CERT,
864 connect_callback.GetResult(client_ret));
865 EXPECT_EQ(ERR_BAD_SSL_CLIENT_AUTH_CERT,
866 handshake_callback.GetResult(server_ret));
867}
ryanchungeb9e3bc2016-03-08 05:08:10868
869TEST_F(SSLServerSocketTest, HandshakeWithWrongClientCertSuppliedCached) {
870 scoped_refptr<X509Certificate> client_cert =
871 ImportCertFromFile(GetTestCertsDirectory(), kClientCertFileName);
rsleevia5c430222016-03-11 05:55:12872 ASSERT_TRUE(client_cert);
873
874 ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForClient(
875 kWrongClientCertFileName, kWrongClientPrivateKeyFileName));
876 ASSERT_NO_FATAL_FAILURE(ConfigureClientCertsForServer());
877 ASSERT_NO_FATAL_FAILURE(CreateContext());
878 ASSERT_NO_FATAL_FAILURE(CreateSockets());
ryanchungeb9e3bc2016-03-08 05:08:10879
880 TestCompletionCallback handshake_callback;
881 int server_ret = server_socket_->Handshake(handshake_callback.callback());
882
883 TestCompletionCallback connect_callback;
884 int client_ret = client_socket_->Connect(connect_callback.callback());
885
886 EXPECT_EQ(ERR_BAD_SSL_CLIENT_AUTH_CERT,
887 connect_callback.GetResult(client_ret));
888 EXPECT_EQ(ERR_BAD_SSL_CLIENT_AUTH_CERT,
889 handshake_callback.GetResult(server_ret));
890
891 client_socket_->Disconnect();
892 server_socket_->Disconnect();
893
894 // Below, check that the cache didn't store the result of a failed handshake.
rsleevia5c430222016-03-11 05:55:12895 ASSERT_NO_FATAL_FAILURE(CreateSockets());
ryanchungeb9e3bc2016-03-08 05:08:10896 TestCompletionCallback handshake_callback2;
897 int server_ret2 = server_socket_->Handshake(handshake_callback2.callback());
898
899 TestCompletionCallback connect_callback2;
900 int client_ret2 = client_socket_->Connect(connect_callback2.callback());
901
902 EXPECT_EQ(ERR_BAD_SSL_CLIENT_AUTH_CERT,
903 connect_callback2.GetResult(client_ret2));
904 EXPECT_EQ(ERR_BAD_SSL_CLIENT_AUTH_CERT,
905 handshake_callback2.GetResult(server_ret2));
906}
ryanchung987b2ff2016-02-19 00:17:12907
[email protected]f61c3972010-12-23 09:54:15908TEST_F(SSLServerSocketTest, DataTransfer) {
rsleevia5c430222016-03-11 05:55:12909 ASSERT_NO_FATAL_FAILURE(CreateContext());
910 ASSERT_NO_FATAL_FAILURE(CreateSockets());
[email protected]f61c3972010-12-23 09:54:15911
[email protected]f61c3972010-12-23 09:54:15912 // Establish connection.
ryanchung987b2ff2016-02-19 00:17:12913 TestCompletionCallback connect_callback;
[email protected]83039bb2011-12-09 18:43:55914 int client_ret = client_socket_->Connect(connect_callback.callback());
[email protected]fa6ce922014-07-17 04:27:04915 ASSERT_TRUE(client_ret == OK || client_ret == ERR_IO_PENDING);
[email protected]f61c3972010-12-23 09:54:15916
ryanchung987b2ff2016-02-19 00:17:12917 TestCompletionCallback handshake_callback;
[email protected]6ea7b152011-12-21 21:21:13918 int server_ret = server_socket_->Handshake(handshake_callback.callback());
[email protected]fa6ce922014-07-17 04:27:04919 ASSERT_TRUE(server_ret == OK || server_ret == ERR_IO_PENDING);
[email protected]f61c3972010-12-23 09:54:15920
[email protected]febbbb52011-08-17 04:59:23921 client_ret = connect_callback.GetResult(client_ret);
robpercival214763f2016-07-01 23:27:01922 ASSERT_THAT(client_ret, IsOk());
[email protected]febbbb52011-08-17 04:59:23923 server_ret = handshake_callback.GetResult(server_ret);
robpercival214763f2016-07-01 23:27:01924 ASSERT_THAT(server_ret, IsOk());
[email protected]f61c3972010-12-23 09:54:15925
926 const int kReadBufSize = 1024;
[email protected]fa6ce922014-07-17 04:27:04927 scoped_refptr<StringIOBuffer> write_buf =
928 new StringIOBuffer("testing123");
929 scoped_refptr<DrainableIOBuffer> read_buf =
930 new DrainableIOBuffer(new IOBuffer(kReadBufSize), kReadBufSize);
[email protected]f61c3972010-12-23 09:54:15931
932 // Write then read.
[email protected]83039bb2011-12-09 18:43:55933 TestCompletionCallback write_callback;
934 TestCompletionCallback read_callback;
ryanchungeb9e3bc2016-03-08 05:08:10935 server_ret = server_socket_->Write(write_buf.get(), write_buf->size(),
936 write_callback.callback());
[email protected]fa6ce922014-07-17 04:27:04937 EXPECT_TRUE(server_ret > 0 || server_ret == ERR_IO_PENDING);
[email protected]90499482013-06-01 00:39:50938 client_ret = client_socket_->Read(
939 read_buf.get(), read_buf->BytesRemaining(), read_callback.callback());
[email protected]fa6ce922014-07-17 04:27:04940 EXPECT_TRUE(client_ret > 0 || client_ret == ERR_IO_PENDING);
[email protected]f61c3972010-12-23 09:54:15941
[email protected]febbbb52011-08-17 04:59:23942 server_ret = write_callback.GetResult(server_ret);
943 EXPECT_GT(server_ret, 0);
944 client_ret = read_callback.GetResult(client_ret);
945 ASSERT_GT(client_ret, 0);
946
947 read_buf->DidConsume(client_ret);
948 while (read_buf->BytesConsumed() < write_buf->size()) {
[email protected]90499482013-06-01 00:39:50949 client_ret = client_socket_->Read(
950 read_buf.get(), read_buf->BytesRemaining(), read_callback.callback());
[email protected]fa6ce922014-07-17 04:27:04951 EXPECT_TRUE(client_ret > 0 || client_ret == ERR_IO_PENDING);
[email protected]febbbb52011-08-17 04:59:23952 client_ret = read_callback.GetResult(client_ret);
953 ASSERT_GT(client_ret, 0);
954 read_buf->DidConsume(client_ret);
[email protected]f61c3972010-12-23 09:54:15955 }
[email protected]febbbb52011-08-17 04:59:23956 EXPECT_EQ(write_buf->size(), read_buf->BytesConsumed());
957 read_buf->SetOffset(0);
[email protected]f61c3972010-12-23 09:54:15958 EXPECT_EQ(0, memcmp(write_buf->data(), read_buf->data(), write_buf->size()));
959
960 // Read then write.
[email protected]fa6ce922014-07-17 04:27:04961 write_buf = new StringIOBuffer("hello123");
[email protected]90499482013-06-01 00:39:50962 server_ret = server_socket_->Read(
963 read_buf.get(), read_buf->BytesRemaining(), read_callback.callback());
[email protected]fa6ce922014-07-17 04:27:04964 EXPECT_TRUE(server_ret > 0 || server_ret == ERR_IO_PENDING);
ryanchungeb9e3bc2016-03-08 05:08:10965 client_ret = client_socket_->Write(write_buf.get(), write_buf->size(),
966 write_callback.callback());
[email protected]fa6ce922014-07-17 04:27:04967 EXPECT_TRUE(client_ret > 0 || client_ret == ERR_IO_PENDING);
[email protected]f61c3972010-12-23 09:54:15968
[email protected]febbbb52011-08-17 04:59:23969 server_ret = read_callback.GetResult(server_ret);
970 ASSERT_GT(server_ret, 0);
971 client_ret = write_callback.GetResult(client_ret);
972 EXPECT_GT(client_ret, 0);
973
974 read_buf->DidConsume(server_ret);
975 while (read_buf->BytesConsumed() < write_buf->size()) {
[email protected]90499482013-06-01 00:39:50976 server_ret = server_socket_->Read(
977 read_buf.get(), read_buf->BytesRemaining(), read_callback.callback());
[email protected]fa6ce922014-07-17 04:27:04978 EXPECT_TRUE(server_ret > 0 || server_ret == ERR_IO_PENDING);
[email protected]febbbb52011-08-17 04:59:23979 server_ret = read_callback.GetResult(server_ret);
980 ASSERT_GT(server_ret, 0);
981 read_buf->DidConsume(server_ret);
[email protected]f61c3972010-12-23 09:54:15982 }
[email protected]febbbb52011-08-17 04:59:23983 EXPECT_EQ(write_buf->size(), read_buf->BytesConsumed());
984 read_buf->SetOffset(0);
[email protected]f61c3972010-12-23 09:54:15985 EXPECT_EQ(0, memcmp(write_buf->data(), read_buf->data(), write_buf->size()));
986}
[email protected]b0ff3f82011-07-23 05:12:39987
[email protected]c0e4dd12012-05-16 19:36:31988// A regression test for bug 127822 (http://crbug.com/127822).
989// If the server closes the connection after the handshake is finished,
990// the client's Write() call should not cause an infinite loop.
991// NOTE: this is a test for SSLClientSocket rather than SSLServerSocket.
[email protected]4da82282014-07-16 18:40:43992TEST_F(SSLServerSocketTest, ClientWriteAfterServerClose) {
rsleevia5c430222016-03-11 05:55:12993 ASSERT_NO_FATAL_FAILURE(CreateContext());
994 ASSERT_NO_FATAL_FAILURE(CreateSockets());
[email protected]c0e4dd12012-05-16 19:36:31995
996 // Establish connection.
ryanchung987b2ff2016-02-19 00:17:12997 TestCompletionCallback connect_callback;
[email protected]c0e4dd12012-05-16 19:36:31998 int client_ret = client_socket_->Connect(connect_callback.callback());
[email protected]fa6ce922014-07-17 04:27:04999 ASSERT_TRUE(client_ret == OK || client_ret == ERR_IO_PENDING);
[email protected]c0e4dd12012-05-16 19:36:311000
ryanchung987b2ff2016-02-19 00:17:121001 TestCompletionCallback handshake_callback;
[email protected]c0e4dd12012-05-16 19:36:311002 int server_ret = server_socket_->Handshake(handshake_callback.callback());
[email protected]fa6ce922014-07-17 04:27:041003 ASSERT_TRUE(server_ret == OK || server_ret == ERR_IO_PENDING);
[email protected]c0e4dd12012-05-16 19:36:311004
1005 client_ret = connect_callback.GetResult(client_ret);
robpercival214763f2016-07-01 23:27:011006 ASSERT_THAT(client_ret, IsOk());
[email protected]c0e4dd12012-05-16 19:36:311007 server_ret = handshake_callback.GetResult(server_ret);
robpercival214763f2016-07-01 23:27:011008 ASSERT_THAT(server_ret, IsOk());
[email protected]c0e4dd12012-05-16 19:36:311009
[email protected]fa6ce922014-07-17 04:27:041010 scoped_refptr<StringIOBuffer> write_buf = new StringIOBuffer("testing123");
[email protected]c0e4dd12012-05-16 19:36:311011
1012 // The server closes the connection. The server needs to write some
1013 // data first so that the client's Read() calls from the transport
1014 // socket won't return ERR_IO_PENDING. This ensures that the client
1015 // will call Read() on the transport socket again.
1016 TestCompletionCallback write_callback;
ryanchungeb9e3bc2016-03-08 05:08:101017 server_ret = server_socket_->Write(write_buf.get(), write_buf->size(),
1018 write_callback.callback());
[email protected]fa6ce922014-07-17 04:27:041019 EXPECT_TRUE(server_ret > 0 || server_ret == ERR_IO_PENDING);
[email protected]c0e4dd12012-05-16 19:36:311020
1021 server_ret = write_callback.GetResult(server_ret);
1022 EXPECT_GT(server_ret, 0);
1023
1024 server_socket_->Disconnect();
1025
1026 // The client writes some data. This should not cause an infinite loop.
ryanchungeb9e3bc2016-03-08 05:08:101027 client_ret = client_socket_->Write(write_buf.get(), write_buf->size(),
1028 write_callback.callback());
[email protected]fa6ce922014-07-17 04:27:041029 EXPECT_TRUE(client_ret > 0 || client_ret == ERR_IO_PENDING);
[email protected]c0e4dd12012-05-16 19:36:311030
1031 client_ret = write_callback.GetResult(client_ret);
1032 EXPECT_GT(client_ret, 0);
1033
skyostil4891b25b2015-06-11 11:43:451034 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
ki.stfu375812e2015-10-09 20:23:171035 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(),
[email protected]c0e4dd12012-05-16 19:36:311036 base::TimeDelta::FromMilliseconds(10));
fdoray5eeb7642016-06-22 16:11:281037 base::RunLoop().Run();
[email protected]c0e4dd12012-05-16 19:36:311038}
1039
[email protected]b0ff3f82011-07-23 05:12:391040// This test executes ExportKeyingMaterial() on the client and server sockets,
1041// after connecting them, and verifies that the results match.
1042// This test will fail if False Start is enabled (see crbug.com/90208).
1043TEST_F(SSLServerSocketTest, ExportKeyingMaterial) {
rsleevia5c430222016-03-11 05:55:121044 ASSERT_NO_FATAL_FAILURE(CreateContext());
1045 ASSERT_NO_FATAL_FAILURE(CreateSockets());
[email protected]b0ff3f82011-07-23 05:12:391046
[email protected]83039bb2011-12-09 18:43:551047 TestCompletionCallback connect_callback;
[email protected]83039bb2011-12-09 18:43:551048 int client_ret = client_socket_->Connect(connect_callback.callback());
[email protected]fa6ce922014-07-17 04:27:041049 ASSERT_TRUE(client_ret == OK || client_ret == ERR_IO_PENDING);
[email protected]b0ff3f82011-07-23 05:12:391050
ryanchung987b2ff2016-02-19 00:17:121051 TestCompletionCallback handshake_callback;
[email protected]6ea7b152011-12-21 21:21:131052 int server_ret = server_socket_->Handshake(handshake_callback.callback());
[email protected]fa6ce922014-07-17 04:27:041053 ASSERT_TRUE(server_ret == OK || server_ret == ERR_IO_PENDING);
[email protected]b0ff3f82011-07-23 05:12:391054
[email protected]fa6ce922014-07-17 04:27:041055 if (client_ret == ERR_IO_PENDING) {
robpercival214763f2016-07-01 23:27:011056 ASSERT_THAT(connect_callback.WaitForResult(), IsOk());
[email protected]b0ff3f82011-07-23 05:12:391057 }
[email protected]fa6ce922014-07-17 04:27:041058 if (server_ret == ERR_IO_PENDING) {
robpercival214763f2016-07-01 23:27:011059 ASSERT_THAT(handshake_callback.WaitForResult(), IsOk());
[email protected]b0ff3f82011-07-23 05:12:391060 }
1061
1062 const int kKeyingMaterialSize = 32;
thestig9d3bb0c2015-01-24 00:49:511063 const char kKeyingLabel[] = "EXPERIMENTAL-server-socket-test";
1064 const char kKeyingContext[] = "";
[email protected]b0ff3f82011-07-23 05:12:391065 unsigned char server_out[kKeyingMaterialSize];
ryanchungeb9e3bc2016-03-08 05:08:101066 int rv = server_socket_->ExportKeyingMaterial(
1067 kKeyingLabel, false, kKeyingContext, server_out, sizeof(server_out));
robpercival214763f2016-07-01 23:27:011068 ASSERT_THAT(rv, IsOk());
[email protected]b0ff3f82011-07-23 05:12:391069
1070 unsigned char client_out[kKeyingMaterialSize];
ryanchungeb9e3bc2016-03-08 05:08:101071 rv = client_socket_->ExportKeyingMaterial(kKeyingLabel, false, kKeyingContext,
[email protected]b0ff3f82011-07-23 05:12:391072 client_out, sizeof(client_out));
robpercival214763f2016-07-01 23:27:011073 ASSERT_THAT(rv, IsOk());
[email protected]47a12862012-04-10 01:00:491074 EXPECT_EQ(0, memcmp(server_out, client_out, sizeof(server_out)));
[email protected]b0ff3f82011-07-23 05:12:391075
thestig9d3bb0c2015-01-24 00:49:511076 const char kKeyingLabelBad[] = "EXPERIMENTAL-server-socket-test-bad";
[email protected]b0ff3f82011-07-23 05:12:391077 unsigned char client_bad[kKeyingMaterialSize];
ryanchungeb9e3bc2016-03-08 05:08:101078 rv = client_socket_->ExportKeyingMaterial(
1079 kKeyingLabelBad, false, kKeyingContext, client_bad, sizeof(client_bad));
[email protected]fa6ce922014-07-17 04:27:041080 ASSERT_EQ(rv, OK);
[email protected]47a12862012-04-10 01:00:491081 EXPECT_NE(0, memcmp(server_out, client_bad, sizeof(server_out)));
[email protected]b0ff3f82011-07-23 05:12:391082}
[email protected]f61c3972010-12-23 09:54:151083
sergeyuff826d5e2015-05-13 20:35:221084// Verifies that SSLConfig::require_ecdhe flags works properly.
1085TEST_F(SSLServerSocketTest, RequireEcdheFlag) {
1086 // Disable all ECDHE suites on the client side.
1087 uint16_t kEcdheCiphers[] = {
1088 0xc007, // ECDHE_ECDSA_WITH_RC4_128_SHA
1089 0xc009, // ECDHE_ECDSA_WITH_AES_128_CBC_SHA
1090 0xc00a, // ECDHE_ECDSA_WITH_AES_256_CBC_SHA
1091 0xc011, // ECDHE_RSA_WITH_RC4_128_SHA
1092 0xc013, // ECDHE_RSA_WITH_AES_128_CBC_SHA
1093 0xc014, // ECDHE_RSA_WITH_AES_256_CBC_SHA
1094 0xc02b, // ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
1095 0xc02f, // ECDHE_RSA_WITH_AES_128_GCM_SHA256
1096 0xcc13, // ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
1097 0xcc14, // ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
1098 };
1099 client_ssl_config_.disabled_cipher_suites.assign(
1100 kEcdheCiphers, kEcdheCiphers + arraysize(kEcdheCiphers));
1101
1102 // Require ECDHE on the server.
1103 server_ssl_config_.require_ecdhe = true;
1104
rsleevia5c430222016-03-11 05:55:121105 ASSERT_NO_FATAL_FAILURE(CreateContext());
1106 ASSERT_NO_FATAL_FAILURE(CreateSockets());
sergeyuff826d5e2015-05-13 20:35:221107
1108 TestCompletionCallback connect_callback;
sergeyuff826d5e2015-05-13 20:35:221109 int client_ret = client_socket_->Connect(connect_callback.callback());
ryanchung987b2ff2016-02-19 00:17:121110
1111 TestCompletionCallback handshake_callback;
sergeyuff826d5e2015-05-13 20:35:221112 int server_ret = server_socket_->Handshake(handshake_callback.callback());
1113
1114 client_ret = connect_callback.GetResult(client_ret);
1115 server_ret = handshake_callback.GetResult(server_ret);
1116
robpercival214763f2016-07-01 23:27:011117 ASSERT_THAT(client_ret, IsError(ERR_SSL_VERSION_OR_CIPHER_MISMATCH));
1118 ASSERT_THAT(server_ret, IsError(ERR_SSL_VERSION_OR_CIPHER_MISMATCH));
sergeyuff826d5e2015-05-13 20:35:221119}
1120
[email protected]f61c3972010-12-23 09:54:151121} // namespace net