ssl_server_socket_openssl.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "net/socket/ssl_server_socket_openssl.h"
6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <openssl/err.h>
8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <openssl/ssl.h>
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/callback_helpers.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "crypto/openssl_util.h"
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "crypto/rsa_private_key.h"
14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "crypto/scoped_openssl_types.h"
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "net/base/net_errors.h"
165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/ssl/openssl_ssl_util.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#define GotoState(s) next_handshake_state_ = s
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnableSSLServerSockets() {
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // No-op because CreateSSLServerSocket() calls crypto::EnsureOpenSSLInit().
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)scoped_ptr<SSLServerSocket> CreateSSLServerSocket(
273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<StreamSocket> socket,
283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    X509Certificate* certificate,
293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    crypto::RSAPrivateKey* key,
303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    const SSLConfig& ssl_config) {
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  crypto::EnsureOpenSSLInit();
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return scoped_ptr<SSLServerSocket>(
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      new SSLServerSocketOpenSSL(socket.Pass(), certificate, key, ssl_config));
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)SSLServerSocketOpenSSL::SSLServerSocketOpenSSL(
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_ptr<StreamSocket> transport_socket,
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_refptr<X509Certificate> certificate,
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    crypto::RSAPrivateKey* key,
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const SSLConfig& ssl_config)
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    : transport_send_busy_(false),
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      transport_recv_busy_(false),
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      transport_recv_eof_(false),
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      user_read_buf_len_(0),
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      user_write_buf_len_(0),
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      transport_write_error_(OK),
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ssl_(NULL),
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      transport_bio_(NULL),
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      transport_socket_(transport_socket.Pass()),
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ssl_config_(ssl_config),
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      cert_(certificate),
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      next_handshake_state_(STATE_NONE),
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      completed_handshake_(false) {
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(byungchul): Need a better way to clone a key.
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::vector<uint8> key_bytes;
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CHECK(key->ExportPrivateKey(&key_bytes));
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  key_.reset(crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_bytes));
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CHECK(key_.get());
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)SSLServerSocketOpenSSL::~SSLServerSocketOpenSSL() {
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (ssl_) {
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Calling SSL_shutdown prevents the session from being marked as
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // unresumable.
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    SSL_shutdown(ssl_);
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    SSL_free(ssl_);
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ssl_ = NULL;
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (transport_bio_) {
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    BIO_free_all(transport_bio_);
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    transport_bio_ = NULL;
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int SSLServerSocketOpenSSL::Handshake(const CompletionCallback& callback) {
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  net_log_.BeginEvent(NetLog::TYPE_SSL_SERVER_HANDSHAKE);
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Set up new ssl object.
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int rv = Init();
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (rv != OK) {
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    LOG(ERROR) << "Failed to initialize OpenSSL: rv=" << rv;
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return rv;
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Set SSL to server mode. Handshake happens in the loop below.
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SSL_set_accept_state(ssl_);
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GotoState(STATE_HANDSHAKE);
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  rv = DoHandshakeLoop(OK);
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    user_handshake_callback_ = callback;
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else {
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return rv > OK ? OK : rv;
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int SSLServerSocketOpenSSL::ExportKeyingMaterial(
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const base::StringPiece& label,
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    bool has_context,
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const base::StringPiece& context,
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    unsigned char* out,
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    unsigned int outlen) {
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!IsConnected())
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return ERR_SOCKET_NOT_CONNECTED;
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int rv = SSL_export_keying_material(
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ssl_, out, outlen, label.data(), label.size(),
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      reinterpret_cast<const unsigned char*>(context.data()),
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      context.length(), context.length() > 0);
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (rv != 1) {
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int ssl_error = SSL_get_error(ssl_, rv);
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    LOG(ERROR) << "Failed to export keying material;"
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)               << " returned " << rv
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)               << ", SSL error code " << ssl_error;
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return MapOpenSSLError(ssl_error, err_tracer);
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return OK;
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int SSLServerSocketOpenSSL::GetTLSUniqueChannelBinding(std::string* out) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTIMPLEMENTED();
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return ERR_NOT_IMPLEMENTED;
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int SSLServerSocketOpenSSL::Read(IOBuffer* buf, int buf_len,
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 const CompletionCallback& callback) {
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(user_read_callback_.is_null());
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(user_handshake_callback_.is_null());
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!user_read_buf_.get());
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!callback.is_null());
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  user_read_buf_ = buf;
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  user_read_buf_len_ = buf_len;
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(completed_handshake_);
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int rv = DoReadLoop(OK);
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    user_read_callback_ = callback;
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else {
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    user_read_buf_ = NULL;
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    user_read_buf_len_ = 0;
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return rv;
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int SSLServerSocketOpenSSL::Write(IOBuffer* buf, int buf_len,
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                  const CompletionCallback& callback) {
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(user_write_callback_.is_null());
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!user_write_buf_.get());
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!callback.is_null());
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  user_write_buf_ = buf;
162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  user_write_buf_len_ = buf_len;
163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int rv = DoWriteLoop(OK);
165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    user_write_callback_ = callback;
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else {
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    user_write_buf_ = NULL;
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    user_write_buf_len_ = 0;
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return rv;
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int SSLServerSocketOpenSSL::SetReceiveBufferSize(int32 size) {
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return transport_socket_->SetReceiveBufferSize(size);
177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int SSLServerSocketOpenSSL::SetSendBufferSize(int32 size) {
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return transport_socket_->SetSendBufferSize(size);
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int SSLServerSocketOpenSSL::Connect(const CompletionCallback& callback) {
184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NOTIMPLEMENTED();
185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return ERR_NOT_IMPLEMENTED;
186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void SSLServerSocketOpenSSL::Disconnect() {
189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  transport_socket_->Disconnect();
190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool SSLServerSocketOpenSSL::IsConnected() const {
193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(wtc): Find out if we should check transport_socket_->IsConnected()
194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // as well.
195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return completed_handshake_;
196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool SSLServerSocketOpenSSL::IsConnectedAndIdle() const {
199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return completed_handshake_ && transport_socket_->IsConnectedAndIdle();
200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int SSLServerSocketOpenSSL::GetPeerAddress(IPEndPoint* address) const {
203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!IsConnected())
204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return ERR_SOCKET_NOT_CONNECTED;
205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return transport_socket_->GetPeerAddress(address);
206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int SSLServerSocketOpenSSL::GetLocalAddress(IPEndPoint* address) const {
209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!IsConnected())
210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return ERR_SOCKET_NOT_CONNECTED;
211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return transport_socket_->GetLocalAddress(address);
212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const BoundNetLog& SSLServerSocketOpenSSL::NetLog() const {
215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return net_log_;
216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void SSLServerSocketOpenSSL::SetSubresourceSpeculation() {
219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  transport_socket_->SetSubresourceSpeculation();
220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void SSLServerSocketOpenSSL::SetOmniboxSpeculation() {
223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  transport_socket_->SetOmniboxSpeculation();
224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool SSLServerSocketOpenSSL::WasEverUsed() const {
227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return transport_socket_->WasEverUsed();
228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool SSLServerSocketOpenSSL::UsingTCPFastOpen() const {
231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return transport_socket_->UsingTCPFastOpen();
232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool SSLServerSocketOpenSSL::WasNpnNegotiated() const {
235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NOTIMPLEMENTED();
236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return false;
237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)NextProto SSLServerSocketOpenSSL::GetNegotiatedProtocol() const {
240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // NPN is not supported by this class.
241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return kProtoUnknown;
242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool SSLServerSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) {
245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NOTIMPLEMENTED();
246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return false;
247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void SSLServerSocketOpenSSL::OnSendComplete(int result) {
250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (next_handshake_state_ == STATE_HANDSHAKE) {
251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // In handshake phase.
252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    OnHandshakeIOComplete(result);
253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(byungchul): This state machine is not correct. Copy the state machine
257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // of SSLClientSocketOpenSSL::OnSendComplete() which handles it better.
258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!completed_handshake_)
259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (user_write_buf_.get()) {
262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int rv = DoWriteLoop(result);
263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (rv != ERR_IO_PENDING)
264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      DoWriteCallback(rv);
265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else {
266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Ensure that any queued ciphertext is flushed.
267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DoTransportIO();
268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
269cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void SSLServerSocketOpenSSL::OnRecvComplete(int result) {
272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (next_handshake_state_ == STATE_HANDSHAKE) {
273cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // In handshake phase.
274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    OnHandshakeIOComplete(result);
275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Network layer received some data, check if client requested to read
279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // decrypted data.
280cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!user_read_buf_.get() || !completed_handshake_)
281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int rv = DoReadLoop(result);
284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (rv != ERR_IO_PENDING)
285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DoReadCallback(rv);
286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void SSLServerSocketOpenSSL::OnHandshakeIOComplete(int result) {
289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int rv = DoHandshakeLoop(result);
290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (rv == ERR_IO_PENDING)
291cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
293cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!user_handshake_callback_.is_null())
295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DoHandshakeCallback(rv);
296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Return 0 for EOF,
299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// > 0 for bytes transferred immediately,
300cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// < 0 for error (or the non-error ERR_IO_PENDING).
301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int SSLServerSocketOpenSSL::BufferSend() {
302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (transport_send_busy_)
303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return ERR_IO_PENDING;
304cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!send_buffer_.get()) {
306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Get a fresh send buffer out of the send BIO.
3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    size_t max_read = BIO_pending(transport_bio_);
308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!max_read)
309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return 0;  // Nothing pending in the OpenSSL write BIO.
310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    send_buffer_ = new DrainableIOBuffer(new IOBuffer(max_read), max_read);
311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int read_bytes = BIO_read(transport_bio_, send_buffer_->data(), max_read);
312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DCHECK_GT(read_bytes, 0);
313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    CHECK_EQ(static_cast<int>(max_read), read_bytes);
314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int rv = transport_socket_->Write(
317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      send_buffer_.get(),
318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      send_buffer_->BytesRemaining(),
319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&SSLServerSocketOpenSSL::BufferSendComplete,
320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 base::Unretained(this)));
321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
322cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    transport_send_busy_ = true;
323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else {
324cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    TransportWriteComplete(rv);
325cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
326cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return rv;
327cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
328cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
329cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void SSLServerSocketOpenSSL::BufferSendComplete(int result) {
330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  transport_send_busy_ = false;
331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  TransportWriteComplete(result);
332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  OnSendComplete(result);
333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void SSLServerSocketOpenSSL::TransportWriteComplete(int result) {
336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(ERR_IO_PENDING != result);
337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (result < 0) {
338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Got a socket write error; close the BIO to indicate this upward.
339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    //
340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // TODO(davidben): The value of |result| gets lost. Feed the error back into
341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // the BIO so it gets (re-)detected in OnSendComplete. Perhaps with
342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // BIO_set_callback.
343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DVLOG(1) << "TransportWriteComplete error " << result;
344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    (void)BIO_shutdown_wr(SSL_get_wbio(ssl_));
345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Match the fix for http://crbug.com/249848 in NSS by erroring future reads
347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // from the socket after a write error.
348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    //
349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // TODO(davidben): Avoid having read and write ends interact this way.
350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    transport_write_error_ = result;
351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    (void)BIO_shutdown_wr(transport_bio_);
352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    send_buffer_ = NULL;
353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else {
354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DCHECK(send_buffer_.get());
355cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    send_buffer_->DidConsume(result);
356cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DCHECK_GE(send_buffer_->BytesRemaining(), 0);
357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (send_buffer_->BytesRemaining() <= 0)
358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      send_buffer_ = NULL;
359cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int SSLServerSocketOpenSSL::BufferRecv() {
363cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (transport_recv_busy_)
364cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return ERR_IO_PENDING;
365cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
366cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Determine how much was requested from |transport_bio_| that was not
367cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // actually available.
368cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t requested = BIO_ctrl_get_read_request(transport_bio_);
369cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (requested == 0) {
370cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // This is not a perfect match of error codes, as no operation is
371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // actually pending. However, returning 0 would be interpreted as
372cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // a possible sign of EOF, which is also an inappropriate match.
373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return ERR_IO_PENDING;
374cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Known Issue: While only reading |requested| data is the more correct
377cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // implementation, it has the downside of resulting in frequent reads:
378cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // One read for the SSL record header (~5 bytes) and one read for the SSL
379cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // record body. Rather than issuing these reads to the underlying socket
380cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // (and constantly allocating new IOBuffers), a single Read() request to
381cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // fill |transport_bio_| is issued. As long as an SSL client socket cannot
382cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // be gracefully shutdown (via SSL close alerts) and re-used for non-SSL
383cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // traffic, this over-subscribed Read()ing will not cause issues.
384cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t max_write = BIO_ctrl_get_write_guarantee(transport_bio_);
385cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!max_write)
386cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return ERR_IO_PENDING;
387cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
388cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  recv_buffer_ = new IOBuffer(max_write);
389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int rv = transport_socket_->Read(
390cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      recv_buffer_.get(),
391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      max_write,
392cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&SSLServerSocketOpenSSL::BufferRecvComplete,
393cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 base::Unretained(this)));
394cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
395cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    transport_recv_busy_ = true;
396cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else {
397cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    rv = TransportReadComplete(rv);
398cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
399cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return rv;
400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
401cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
402cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void SSLServerSocketOpenSSL::BufferRecvComplete(int result) {
403cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  result = TransportReadComplete(result);
404cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  OnRecvComplete(result);
405cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int SSLServerSocketOpenSSL::TransportReadComplete(int result) {
408cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(ERR_IO_PENDING != result);
409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (result <= 0) {
410cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DVLOG(1) << "TransportReadComplete result " << result;
411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Received 0 (end of file) or an error. Either way, bubble it up to the
412cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // SSL layer via the BIO. TODO(joth): consider stashing the error code, to
413cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // relay up to the SSL socket client (i.e. via DoReadCallback).
414cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (result == 0)
415cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      transport_recv_eof_ = true;
416cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    (void)BIO_shutdown_wr(transport_bio_);
417cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else if (transport_write_error_ < 0) {
418cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Mirror transport write errors as read failures; transport_bio_ has been
419cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // shut down by TransportWriteComplete, so the BIO_write will fail, failing
420cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // the CHECK. http://crbug.com/335557.
421cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    result = transport_write_error_;
422cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else {
423cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DCHECK(recv_buffer_.get());
424cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int ret = BIO_write(transport_bio_, recv_buffer_->data(), result);
425cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // A write into a memory BIO should always succeed.
426cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DCHECK_EQ(result, ret);
427cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
428cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  recv_buffer_ = NULL;
429cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  transport_recv_busy_ = false;
430cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return result;
431cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
432cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
433cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Do as much network I/O as possible between the buffer and the
434cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// transport socket. Return true if some I/O performed, false
435cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// otherwise (error or ERR_IO_PENDING).
436cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool SSLServerSocketOpenSSL::DoTransportIO() {
437cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool network_moved = false;
438cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int rv;
439cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Read and write as much data as possible. The loop is necessary because
440cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Write() may return synchronously.
441cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  do {
442cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    rv = BufferSend();
443cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (rv != ERR_IO_PENDING && rv != 0)
444cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      network_moved = true;
445cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } while (rv > 0);
446cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!transport_recv_eof_ && BufferRecv() != ERR_IO_PENDING)
447cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    network_moved = true;
448cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return network_moved;
449cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
450cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
451cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int SSLServerSocketOpenSSL::DoPayloadRead() {
452cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(user_read_buf_.get());
453cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_GT(user_read_buf_len_, 0);
454cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
455cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int rv = SSL_read(ssl_, user_read_buf_->data(), user_read_buf_len_);
456cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (rv >= 0)
457cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return rv;
458cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int ssl_error = SSL_get_error(ssl_, rv);
4591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  OpenSSLErrorInfo error_info;
4601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int net_error = MapOpenSSLErrorWithDetails(ssl_error, err_tracer,
4611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                             &error_info);
462cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (net_error != ERR_IO_PENDING) {
4631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    net_log_.AddEvent(
4641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        NetLog::TYPE_SSL_READ_ERROR,
4651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        CreateNetLogOpenSSLErrorCallback(net_error, ssl_error, error_info));
466cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
467cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return net_error;
468cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
469cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
470cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int SSLServerSocketOpenSSL::DoPayloadWrite() {
471cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(user_write_buf_.get());
472cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
473cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_);
474cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (rv >= 0)
475cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return rv;
476cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int ssl_error = SSL_get_error(ssl_, rv);
4771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  OpenSSLErrorInfo error_info;
4781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  int net_error = MapOpenSSLErrorWithDetails(ssl_error, err_tracer,
4791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                             &error_info);
480cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (net_error != ERR_IO_PENDING) {
4811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    net_log_.AddEvent(
4821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        NetLog::TYPE_SSL_WRITE_ERROR,
4831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        CreateNetLogOpenSSLErrorCallback(net_error, ssl_error, error_info));
484cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
485cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return net_error;
486cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
487cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
488cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int SSLServerSocketOpenSSL::DoHandshakeLoop(int last_io_result) {
489cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int rv = last_io_result;
490cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  do {
491cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Default to STATE_NONE for next state.
492cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // (This is a quirk carried over from the windows
493cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // implementation.  It makes reading the logs a bit harder.)
494cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // State handlers can and often do call GotoState just
495cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // to stay in the current state.
496cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    State state = next_handshake_state_;
497cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    GotoState(STATE_NONE);
498cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    switch (state) {
499cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      case STATE_HANDSHAKE:
500cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        rv = DoHandshake();
501cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        break;
502cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      case STATE_NONE:
503cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      default:
504cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        rv = ERR_UNEXPECTED;
505cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        LOG(DFATAL) << "unexpected state " << state;
506cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        break;
507cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
508cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
509cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Do the actual network I/O
510cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    bool network_moved = DoTransportIO();
511cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (network_moved && next_handshake_state_ == STATE_HANDSHAKE) {
512cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // In general we exit the loop if rv is ERR_IO_PENDING.  In this
513cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // special case we keep looping even if rv is ERR_IO_PENDING because
514cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // the transport IO may allow DoHandshake to make progress.
515cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      rv = OK;  // This causes us to stay in the loop.
516cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
517cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
518cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return rv;
519cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
520cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
521cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int SSLServerSocketOpenSSL::DoReadLoop(int result) {
522cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(completed_handshake_);
523cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(next_handshake_state_ == STATE_NONE);
524cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
525cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (result < 0)
526cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return result;
527cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
528cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool network_moved;
529cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int rv;
530cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  do {
531cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    rv = DoPayloadRead();
532cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    network_moved = DoTransportIO();
533cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } while (rv == ERR_IO_PENDING && network_moved);
534cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return rv;
535cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
536cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
537cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int SSLServerSocketOpenSSL::DoWriteLoop(int result) {
538cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(completed_handshake_);
539cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_EQ(next_handshake_state_, STATE_NONE);
540cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
541cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (result < 0)
542cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return result;
543cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
544cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool network_moved;
545cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int rv;
546cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  do {
547cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    rv = DoPayloadWrite();
548cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    network_moved = DoTransportIO();
549cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } while (rv == ERR_IO_PENDING && network_moved);
550cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return rv;
551cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
552cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
553cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int SSLServerSocketOpenSSL::DoHandshake() {
554cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
555cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int net_error = OK;
556cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  int rv = SSL_do_handshake(ssl_);
557cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
558cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (rv == 1) {
559cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    completed_handshake_ = true;
560cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else {
561cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int ssl_error = SSL_get_error(ssl_, rv);
5621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    OpenSSLErrorInfo error_info;
5631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    net_error = MapOpenSSLErrorWithDetails(ssl_error, err_tracer, &error_info);
564cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
565cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // If not done, stay in this state
566cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (net_error == ERR_IO_PENDING) {
567cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      GotoState(STATE_HANDSHAKE);
568cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    } else {
569cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      LOG(ERROR) << "handshake failed; returned " << rv
570cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 << ", SSL error code " << ssl_error
571cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 << ", net_error " << net_error;
5721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      net_log_.AddEvent(
5731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          NetLog::TYPE_SSL_HANDSHAKE_ERROR,
5741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          CreateNetLogOpenSSLErrorCallback(net_error, ssl_error, error_info));
575cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
576cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
577cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return net_error;
578cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
579cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
580cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void SSLServerSocketOpenSSL::DoHandshakeCallback(int rv) {
581cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_NE(rv, ERR_IO_PENDING);
582cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ResetAndReturn(&user_handshake_callback_).Run(rv > OK ? OK : rv);
583cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
584cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
585cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void SSLServerSocketOpenSSL::DoReadCallback(int rv) {
586cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(rv != ERR_IO_PENDING);
587cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!user_read_callback_.is_null());
588cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
589cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  user_read_buf_ = NULL;
590cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  user_read_buf_len_ = 0;
591cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ResetAndReturn(&user_read_callback_).Run(rv);
592cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
593cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
594cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void SSLServerSocketOpenSSL::DoWriteCallback(int rv) {
595cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(rv != ERR_IO_PENDING);
596cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!user_write_callback_.is_null());
597cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
598cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  user_write_buf_ = NULL;
599cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  user_write_buf_len_ = 0;
600cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ResetAndReturn(&user_write_callback_).Run(rv);
601cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
602cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
603cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int SSLServerSocketOpenSSL::Init() {
604cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!ssl_);
605cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!transport_bio_);
606cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
607cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
608cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
609116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  crypto::ScopedOpenSSL<SSL_CTX, SSL_CTX_free>::Type ssl_ctx(
610cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // It support SSLv2, SSLv3, and TLSv1.
611cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      SSL_CTX_new(SSLv23_server_method()));
612cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ssl_ = SSL_new(ssl_ctx.get());
613cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!ssl_)
614cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return ERR_UNEXPECTED;
615cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
616cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  BIO* ssl_bio = NULL;
617cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // 0 => use default buffer sizes.
618cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0))
619cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return ERR_UNEXPECTED;
620cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(ssl_bio);
621cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(transport_bio_);
622cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
623cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SSL_set_bio(ssl_, ssl_bio, ssl_bio);
624cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
625cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Set certificate and private key.
626cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(cert_->os_cert_handle());
627f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#if defined(USE_OPENSSL_CERTS)
628cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (SSL_use_certificate(ssl_, cert_->os_cert_handle()) != 1) {
629cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    LOG(ERROR) << "Cannot set certificate.";
630cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return ERR_UNEXPECTED;
631cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
632f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#else
633f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Convert OSCertHandle to X509 structure.
634f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  std::string der_string;
635f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!X509Certificate::GetDEREncoded(cert_->os_cert_handle(), &der_string))
636f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return ERR_UNEXPECTED;
637f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
638f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const unsigned char* der_string_array =
639f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      reinterpret_cast<const unsigned char*>(der_string.data());
640f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
641116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  crypto::ScopedOpenSSL<X509, X509_free>::Type x509(
642116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      d2i_X509(NULL, &der_string_array, der_string.length()));
643f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!x509.get())
644f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return ERR_UNEXPECTED;
645f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
646f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // On success, SSL_use_certificate acquires a reference to |x509|.
647f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (SSL_use_certificate(ssl_, x509.get()) != 1) {
648f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LOG(ERROR) << "Cannot set certificate.";
649f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return ERR_UNEXPECTED;
650f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
651f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif  // USE_OPENSSL_CERTS
652cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
653cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(key_->key());
654cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (SSL_use_PrivateKey(ssl_, key_->key()) != 1) {
655cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    LOG(ERROR) << "Cannot set private key.";
656cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return ERR_UNEXPECTED;
657cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
658cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
659cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // OpenSSL defaults some options to on, others to off. To avoid ambiguity,
660cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // set everything we care about to an absolute value.
661cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SslSetClearMask options;
662cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  options.ConfigureFlag(SSL_OP_NO_SSLv2, true);
663cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool ssl3_enabled = (ssl_config_.version_min == SSL_PROTOCOL_VERSION_SSL3);
664cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  options.ConfigureFlag(SSL_OP_NO_SSLv3, !ssl3_enabled);
665cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool tls1_enabled = (ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1 &&
666cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1);
667cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  options.ConfigureFlag(SSL_OP_NO_TLSv1, !tls1_enabled);
668cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool tls1_1_enabled =
669cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      (ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1_1 &&
670cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1_1);
671cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  options.ConfigureFlag(SSL_OP_NO_TLSv1_1, !tls1_1_enabled);
672cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool tls1_2_enabled =
673cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      (ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1_2 &&
674cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)       ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1_2);
675cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  options.ConfigureFlag(SSL_OP_NO_TLSv1_2, !tls1_2_enabled);
676cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
677cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  options.ConfigureFlag(SSL_OP_NO_COMPRESSION, true);
678cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
679cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SSL_set_options(ssl_, options.set_mask);
680cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SSL_clear_options(ssl_, options.clear_mask);
681cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
682cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Same as above, this time for the SSL mode.
683cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SslSetClearMask mode;
684cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
685cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  mode.ConfigureFlag(SSL_MODE_RELEASE_BUFFERS, true);
686cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
687cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SSL_set_mode(ssl_, mode.set_mask);
688cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SSL_clear_mode(ssl_, mode.clear_mask);
689cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
690cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return OK;
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
694