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