1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick// Use of this source code is governed by a BSD-style license that can be
3c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick// found in the LICENSE file.
4c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick
5c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick// OpenSSL binding for SSLClientSocket. The class layout and general principle
6c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick// of operation is derived from SSLClientSocketNSS.
700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch#include "net/socket/ssl_client_socket_openssl.h"
900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
10c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick#include <openssl/ssl.h>
11c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick#include <openssl/err.h>
120dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen#ifdef ANDROID
130dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen#include <string>
140dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen#endif
15c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick
16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/singleton.h"
17731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/metrics/histogram.h"
1872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/synchronization/lock.h"
19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "crypto/openssl_util.h"
204a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "net/base/cert_verifier.h"
2100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch#include "net/base/net_errors.h"
2221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "net/base/openssl_private_key_store.h"
2321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "net/base/ssl_cert_request_info.h"
24c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick#include "net/base/ssl_connection_status_flags.h"
25c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick#include "net/base/ssl_info.h"
2621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "net/socket/ssl_error_params.h"
2700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
2800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdochnamespace net {
2900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
30c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merricknamespace {
31c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick
32c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick// Enable this to see logging for state machine state transitions.
33c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick#if 0
34731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#define GotoState(s) do { DVLOG(2) << (void *)this << " " << __FUNCTION__ << \
3500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch                           " jump to state " << s; \
3600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch                           next_handshake_state_ = s; } while (0)
37c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick#else
38c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick#define GotoState(s) next_handshake_state_ = s
3900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch#endif
4000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
41c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrickconst size_t kMaxRecvBufferSize = 4096;
42201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochconst int kSessionCacheTimeoutSeconds = 60 * 60;
43201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochconst size_t kSessionCacheMaxEntires = 1024;
4400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
45731158395b8ae1105c69cc42dae6244385f6b4ffBrian Carlstrom#if OPENSSL_VERSION_NUMBER < 0x1000100fL
46731158395b8ae1105c69cc42dae6244385f6b4ffBrian Carlstrom// This method was first included in OpenSSL 1.0.1.
47731158395b8ae1105c69cc42dae6244385f6b4ffBrian Carlstromunsigned long SSL_CIPHER_get_id(const SSL_CIPHER* cipher) { return cipher->id; }
48731158395b8ae1105c69cc42dae6244385f6b4ffBrian Carlstrom#endif
49731158395b8ae1105c69cc42dae6244385f6b4ffBrian Carlstrom
5021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Used for encoding the |connection_status| field of an SSLInfo object.
5121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenint EncodeSSLConnectionStatus(int cipher_suite,
5221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                              int compression,
5321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                              int version) {
5421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return ((cipher_suite & SSL_CONNECTION_CIPHERSUITE_MASK) <<
5521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          SSL_CONNECTION_CIPHERSUITE_SHIFT) |
5621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen         ((compression & SSL_CONNECTION_COMPRESSION_MASK) <<
5721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          SSL_CONNECTION_COMPRESSION_SHIFT) |
5821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen         ((version & SSL_CONNECTION_VERSION_MASK) <<
5921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          SSL_CONNECTION_VERSION_SHIFT);
6021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
6121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
6221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Returns the net SSL version number (see ssl_connection_status_flags.h) for
6321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// this SSL connection.
6421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenint GetNetSSLVersion(SSL* ssl) {
6521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  switch (SSL_version(ssl)) {
6621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL2_VERSION:
6721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return SSL_CONNECTION_VERSION_SSL2;
6821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL3_VERSION:
6921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return SSL_CONNECTION_VERSION_SSL3;
7021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case TLS1_VERSION:
7121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return SSL_CONNECTION_VERSION_TLS1;
7221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case 0x0302:
7321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return SSL_CONNECTION_VERSION_TLS1_1;
7421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case 0x0303:
7521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return SSL_CONNECTION_VERSION_TLS1_2;
7621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    default:
7721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return SSL_CONNECTION_VERSION_UNKNOWN;
7821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
7921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
8021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
8121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenint MapOpenSSLErrorSSL() {
8221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Walk down the error stack to find the SSLerr generated reason.
8321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  unsigned long error_code;
8421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  do {
8521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    error_code = ERR_get_error();
8621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (error_code == 0)
8721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return ERR_SSL_PROTOCOL_ERROR;
8821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  } while (ERR_GET_LIB(error_code) != ERR_LIB_SSL);
8921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
9021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DVLOG(1) << "OpenSSL SSL error, reason: " << ERR_GET_REASON(error_code)
9121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen           << ", name: " << ERR_error_string(error_code, NULL);
9221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  switch (ERR_GET_REASON(error_code)) {
9321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_READ_TIMEOUT_EXPIRED:
9421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return ERR_TIMED_OUT;
9521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_BAD_RESPONSE_ARGUMENT:
9621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return ERR_INVALID_ARGUMENT;
9721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_UNKNOWN_CERTIFICATE_TYPE:
9821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_UNKNOWN_CIPHER_TYPE:
9921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE:
10021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_UNKNOWN_PKEY_TYPE:
10121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_UNKNOWN_REMOTE_ERROR_TYPE:
10221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_UNKNOWN_SSL_VERSION:
10321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return ERR_NOT_IMPLEMENTED;
10421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_UNSUPPORTED_SSL_VERSION:
10521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_NO_CIPHER_MATCH:
10621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_NO_SHARED_CIPHER:
10721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY:
10821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION:
10921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return ERR_SSL_VERSION_OR_CIPHER_MISMATCH;
11021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_SSLV3_ALERT_BAD_CERTIFICATE:
11121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE:
11221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED:
11321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED:
11421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN:
11521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_TLSV1_ALERT_ACCESS_DENIED:
11621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_TLSV1_ALERT_UNKNOWN_CA:
11721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return ERR_BAD_SSL_CLIENT_AUTH_CERT;
11821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_BAD_DECOMPRESSION:
11921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE:
12021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return ERR_SSL_DECOMPRESSION_FAILURE_ALERT;
12121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_SSLV3_ALERT_BAD_RECORD_MAC:
12221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return ERR_SSL_BAD_RECORD_MAC_ALERT;
12321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED:
12421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return ERR_SSL_UNSAFE_NEGOTIATION;
12521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_WRONG_NUMBER_OF_KEY_BITS:
12621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY;
12721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // SSL_R_UNKNOWN_PROTOCOL is reported if premature application data is
12821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // received (see http://crbug.com/42538), and also if all the protocol
12921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // versions supported by the server were disabled in this socket instance.
13021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // Mapped to ERR_SSL_PROTOCOL_ERROR for compatibility with other SSL sockets
13121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // in the former scenario.
13221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_UNKNOWN_PROTOCOL:
13321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_SSL_HANDSHAKE_FAILURE:
13421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_DECRYPTION_FAILED:
13521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC:
13621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG:
13721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_DIGEST_CHECK_FAILED:
13821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_DUPLICATE_COMPRESSION_ID:
13921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER:
14021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_ENCRYPTED_LENGTH_TOO_LONG:
14121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST:
14221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_EXCESSIVE_MESSAGE_SIZE:
14321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_EXTRA_DATA_IN_MESSAGE:
14421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_GOT_A_FIN_BEFORE_A_CCS:
14521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_ILLEGAL_PADDING:
14621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_INVALID_CHALLENGE_LENGTH:
14721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_INVALID_COMMAND:
14821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_INVALID_PURPOSE:
14921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_INVALID_STATUS_RESPONSE:
15021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_INVALID_TICKET_KEYS_LENGTH:
15121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_KEY_ARG_TOO_LONG:
15221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_READ_WRONG_PACKET_TYPE:
15321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE:
15421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // TODO(joth): SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE may be returned from the
15521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // server after receiving ClientHello if there's no common supported cipher.
15621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // Ideally we'd map that specific case to ERR_SSL_VERSION_OR_CIPHER_MISMATCH
15721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // to match the NSS implementation. See also http://goo.gl/oMtZW
15821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE:
15921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_SSLV3_ALERT_NO_CERTIFICATE:
16021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER:
16121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_TLSV1_ALERT_DECODE_ERROR:
16221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_TLSV1_ALERT_DECRYPTION_FAILED:
16321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_TLSV1_ALERT_DECRYPT_ERROR:
16421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION:
16521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_TLSV1_ALERT_INTERNAL_ERROR:
16621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_TLSV1_ALERT_NO_RENEGOTIATION:
16721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_TLSV1_ALERT_RECORD_OVERFLOW:
16821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_R_TLSV1_ALERT_USER_CANCELLED:
16921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return ERR_SSL_PROTOCOL_ERROR;
17021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    default:
17121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      LOG(WARNING) << "Unmapped error reason: " << ERR_GET_REASON(error_code);
17221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return ERR_FAILED;
17321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
17421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
17521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
17621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Converts an OpenSSL error code into a net error code, walking the OpenSSL
17721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// error stack if needed. Note that |tracer| is not currently used in the
17821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// implementation, but is passed in anyway as this ensures the caller will clear
17921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// any residual codes left on the error stack.
180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint MapOpenSSLError(int err, const crypto::OpenSSLErrStackTracer& tracer) {
181c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  switch (err) {
182c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    case SSL_ERROR_WANT_READ:
183c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    case SSL_ERROR_WANT_WRITE:
184c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick      return ERR_IO_PENDING;
185731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    case SSL_ERROR_SYSCALL:
186731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      DVLOG(1) << "OpenSSL SYSCALL error, errno " << errno;
187731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      return ERR_SSL_PROTOCOL_ERROR;
18821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    case SSL_ERROR_SSL:
18921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return MapOpenSSLErrorSSL();
190c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    default:
191c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick      // TODO(joth): Implement full mapping.
192c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick      LOG(WARNING) << "Unknown OpenSSL error " << err;
193c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick      return ERR_SSL_PROTOCOL_ERROR;
19400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  }
19500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
19600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
1974a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// We do certificate verification after handshake, so we disable the default
1984a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch// by registering a no-op verify function.
1994a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochint NoOpVerifyCallback(X509_STORE_CTX*, void *) {
2004a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  DVLOG(3) << "skipping cert verify";
2014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  return 1;
2024a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch}
2034a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
204201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// OpenSSL manages a cache of SSL_SESSION, this class provides the application
205201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// side policy for that cache about session re-use: we retain one session per
206201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// unique HostPortPair.
207201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochclass SSLSessionCache {
208201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch public:
209201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  SSLSessionCache() {}
210201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
211201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  void OnSessionAdded(const HostPortPair& host_and_port, SSL_SESSION* session) {
212201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // Declare the session cleaner-upper before the lock, so any call into
213201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // OpenSSL to free the session will happen after the lock is released.
214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    crypto::ScopedOpenSSL<SSL_SESSION, SSL_SESSION_free> session_to_free;
21572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    base::AutoLock lock(lock_);
216201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
217201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    DCHECK_EQ(0U, session_map_.count(session));
218201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    std::pair<HostPortMap::iterator, bool> res =
219201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        host_port_map_.insert(std::make_pair(host_and_port, session));
220201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (!res.second) {  // Already exists: replace old entry.
221201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      session_to_free.reset(res.first->second);
222201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      session_map_.erase(session_to_free.get());
223201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      res.first->second = session;
224201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    }
225201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    DVLOG(2) << "Adding session " << session << " => "
226201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch             << host_and_port.ToString() << ", new entry = " << res.second;
227201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    DCHECK(host_port_map_[host_and_port] == session);
228201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    session_map_[session] = res.first;
229201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    DCHECK_EQ(host_port_map_.size(), session_map_.size());
230201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    DCHECK_LE(host_port_map_.size(), kSessionCacheMaxEntires);
2314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
232201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
233201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  void OnSessionRemoved(SSL_SESSION* session) {
234201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // Declare the session cleaner-upper before the lock, so any call into
235201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // OpenSSL to free the session will happen after the lock is released.
236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    crypto::ScopedOpenSSL<SSL_SESSION, SSL_SESSION_free> session_to_free;
23772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    base::AutoLock lock(lock_);
238201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
239201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    SessionMap::iterator it = session_map_.find(session);
240201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (it == session_map_.end())
241201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      return;
242201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    DVLOG(2) << "Remove session " << session << " => "
243201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch             << it->second->first.ToString();
244201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    DCHECK(it->second->second == session);
245201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    host_port_map_.erase(it->second);
246201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    session_map_.erase(it);
247201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    session_to_free.reset(session);
248201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    DCHECK_EQ(host_port_map_.size(), session_map_.size());
2494a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  }
250201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
251201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Looks up the host:port in the cache, and if a session is found it is added
252201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // to |ssl|, returning true on success.
253201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  bool SetSSLSession(SSL* ssl, const HostPortPair& host_and_port) {
25472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    base::AutoLock lock(lock_);
255201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    HostPortMap::iterator it = host_port_map_.find(host_and_port);
256201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (it == host_port_map_.end())
257201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      return false;
258201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    DVLOG(2) << "Lookup session: " << it->second << " => "
259201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch             << host_and_port.ToString();
260201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    SSL_SESSION* session = it->second;
261201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    DCHECK(session);
262201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    DCHECK(session_map_[session] == it);
263201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // Ideally we'd release |lock_| before calling into OpenSSL here, however
264201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // that opens a small risk |session| will go out of scope before it is used.
265201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // Alternatively we would take a temporary local refcount on |session|,
266201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // except OpenSSL does not provide a public API for adding a ref (c.f.
267201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // SSL_SESSION_free which decrements the ref).
268201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return SSL_set_session(ssl, session) == 1;
269201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
270201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
271201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch private:
272201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // A pair of maps to allow bi-directional lookups between host:port and an
27321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // associated session.
274201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // TODO(joth): When client certificates are implemented we should key the
275201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // cache on the client certificate used in addition to the host-port pair.
276201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  typedef std::map<HostPortPair, SSL_SESSION*> HostPortMap;
277201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  typedef std::map<SSL_SESSION*, HostPortMap::iterator> SessionMap;
278201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  HostPortMap host_port_map_;
279201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  SessionMap session_map_;
280201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
281201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Protects access to both the above maps.
28272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  base::Lock lock_;
283201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
284201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(SSLSessionCache);
2854a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch};
2864a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
287201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochclass SSLContext {
288201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch public:
28921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  static SSLContext* GetInstance() { return Singleton<SSLContext>::get(); }
290201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  SSL_CTX* ssl_ctx() { return ssl_ctx_.get(); }
291201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  SSLSessionCache* session_cache() { return &session_cache_; }
292201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
293201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  SSLClientSocketOpenSSL* GetClientSocketFromSSL(SSL* ssl) {
294201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    DCHECK(ssl);
295201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    SSLClientSocketOpenSSL* socket = static_cast<SSLClientSocketOpenSSL*>(
296201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        SSL_get_ex_data(ssl, ssl_socket_data_index_));
297201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    DCHECK(socket);
298201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return socket;
299201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
300201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
301201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  bool SetClientSocketForSSL(SSL* ssl, SSLClientSocketOpenSSL* socket) {
302201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return SSL_set_ex_data(ssl, ssl_socket_data_index_, socket) != 0;
303201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
304201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
305201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch private:
306201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  friend struct DefaultSingletonTraits<SSLContext>;
307201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
308201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  SSLContext() {
309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    crypto::EnsureOpenSSLInit();
310201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0);
311201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    DCHECK_NE(ssl_socket_data_index_, -1);
312201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    ssl_ctx_.reset(SSL_CTX_new(SSLv23_client_method()));
313201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), NoOpVerifyCallback, NULL);
314201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    SSL_CTX_set_session_cache_mode(ssl_ctx_.get(), SSL_SESS_CACHE_CLIENT);
315201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    SSL_CTX_sess_set_new_cb(ssl_ctx_.get(), NewSessionCallbackStatic);
316201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    SSL_CTX_sess_set_remove_cb(ssl_ctx_.get(), RemoveSessionCallbackStatic);
317201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    SSL_CTX_set_timeout(ssl_ctx_.get(), kSessionCacheTimeoutSeconds);
318201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    SSL_CTX_sess_set_cache_size(ssl_ctx_.get(), kSessionCacheMaxEntires);
31921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    SSL_CTX_set_client_cert_cb(ssl_ctx_.get(), ClientCertCallback);
3200dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen#if defined(OPENSSL_NPN_NEGOTIATED)
3210dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen    // TODO(kristianm): Only select this if ssl_config_.next_proto is not empty.
3220dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen    // It would be better if the callback were not a global setting,
3230dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen    // but that is an OpenSSL issue.
3240dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen    SSL_CTX_set_next_proto_select_cb(ssl_ctx_.get(), SelectNextProtoCallback,
3250dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen                                     NULL);
3260dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen#endif
327201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
328201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
329201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static int NewSessionCallbackStatic(SSL* ssl, SSL_SESSION* session) {
33021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return GetInstance()->NewSessionCallback(ssl, session);
331201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
332201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
333201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  int NewSessionCallback(SSL* ssl, SSL_SESSION* session) {
334201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    SSLClientSocketOpenSSL* socket = GetClientSocketFromSSL(ssl);
335201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    session_cache_.OnSessionAdded(socket->host_and_port(), session);
336201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return 1;  // 1 => We took ownership of |session|.
337201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
338201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
339201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  static void RemoveSessionCallbackStatic(SSL_CTX* ctx, SSL_SESSION* session) {
34021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return GetInstance()->RemoveSessionCallback(ctx, session);
341201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
342201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
343201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  void RemoveSessionCallback(SSL_CTX* ctx, SSL_SESSION* session) {
344201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    DCHECK(ctx == ssl_ctx());
345201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    session_cache_.OnSessionRemoved(session);
346201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
347201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
34821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  static int ClientCertCallback(SSL* ssl, X509** x509, EVP_PKEY** pkey) {
34921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl);
35021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    CHECK(socket);
35121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return socket->ClientCertRequestCallback(ssl, x509, pkey);
35221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
35321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
3540dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen  static int SelectNextProtoCallback(SSL* ssl,
3550dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen                                     unsigned char** out, unsigned char* outlen,
3560dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen                                     const unsigned char* in,
3570dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen                                     unsigned int inlen, void* arg) {
35821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl);
35921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return socket->SelectNextProtoCallback(out, outlen, in, inlen);
36021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
3610dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen
362201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // This is the index used with SSL_get_ex_data to retrieve the owner
363201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // SSLClientSocketOpenSSL object from an SSL instance.
364201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  int ssl_socket_data_index_;
365201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
366ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  crypto::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_;
367201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  SSLSessionCache session_cache_;
368201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch};
3694a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
3708db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom// Utility to construct the appropriate set & clear masks for use the OpenSSL
3718db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom// options and mode configuration functions. (SSL_set_options etc)
3728db08726a8eea9d32f637ced774aac6b16416071Brian Carlstromstruct SslSetClearMask {
3738db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom  SslSetClearMask() : set_mask(0), clear_mask(0) {}
3748db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom  void ConfigureFlag(long flag, bool state) {
3758db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom    (state ? set_mask : clear_mask) |= flag;
3768db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom    // Make sure we haven't got any intersection in the set & clear options.
3778db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom    DCHECK_EQ(0, set_mask & clear_mask) << flag << ":" << state;
3788db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom  }
3798db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom  long set_mask;
3808db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom  long clear_mask;
3818db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom};
3828db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom
383c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick}  // namespace
384c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick
385c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain MerrickSSLClientSocketOpenSSL::SSLClientSocketOpenSSL(
386c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    ClientSocketHandle* transport_socket,
3874a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    const HostPortPair& host_and_port,
38821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const SSLConfig& ssl_config,
38921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    CertVerifier* cert_verifier)
390c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    : ALLOW_THIS_IN_INITIALIZER_LIST(buffer_send_callback_(
391c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick          this, &SSLClientSocketOpenSSL::BufferSendComplete)),
392c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick      ALLOW_THIS_IN_INITIALIZER_LIST(buffer_recv_callback_(
393c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick          this, &SSLClientSocketOpenSSL::BufferRecvComplete)),
394c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick      transport_send_busy_(false),
39500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch      transport_recv_busy_(false),
39600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch      user_connect_callback_(NULL),
39700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch      user_read_callback_(NULL),
39800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch      user_write_callback_(NULL),
399201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      completed_handshake_(false),
40000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch      client_auth_cert_needed_(false),
40121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      cert_verifier_(cert_verifier),
402731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      ALLOW_THIS_IN_INITIALIZER_LIST(handshake_io_callback_(
403731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick          this, &SSLClientSocketOpenSSL::OnHandshakeIOComplete)),
404c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick      ssl_(NULL),
405c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick      transport_bio_(NULL),
40600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch      transport_(transport_socket),
4074a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch      host_and_port_(host_and_port),
40800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch      ssl_config_(ssl_config),
409201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      trying_cached_session_(false),
41021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      npn_status_(kNextProtoUnsupported),
41100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch      net_log_(transport_socket->socket()->NetLog()) {
41200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
41300d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
41400d26a728db2814620f390b418a7d6325ce5aca6Ben MurdochSSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() {
41500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  Disconnect();
41600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
41700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
418c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrickbool SSLClientSocketOpenSSL::Init() {
419731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(!ssl_);
420731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(!transport_bio_);
421731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
42221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  SSLContext* context = SSLContext::GetInstance();
423ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
424201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
425201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  ssl_ = SSL_new(context->ssl_ctx());
426201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (!ssl_ || !context->SetClientSocketForSSL(ssl_, this))
427c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    return false;
428c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick
429201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (!SSL_set_tlsext_host_name(ssl_, host_and_port_.host().c_str()))
430c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    return false;
431201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
432201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  trying_cached_session_ =
433201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      context->session_cache()->SetSSLSession(ssl_, host_and_port_);
434c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick
435c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  BIO* ssl_bio = NULL;
436201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // 0 => use default buffer sizes.
437201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0))
438c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    return false;
439c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  DCHECK(ssl_bio);
440c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  DCHECK(transport_bio_);
441c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick
442c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  SSL_set_bio(ssl_, ssl_bio, ssl_bio);
443c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick
444731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // OpenSSL defaults some options to on, others to off. To avoid ambiguity,
445731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // set everything we care about to an absolute value.
4468db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom  SslSetClearMask options;
4478db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom  options.ConfigureFlag(SSL_OP_NO_SSLv2, true);
4488db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom  options.ConfigureFlag(SSL_OP_NO_SSLv3, !ssl_config_.ssl3_enabled);
4498db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom  options.ConfigureFlag(SSL_OP_NO_TLSv1, !ssl_config_.tls1_enabled);
450fb292835997c64a14669de65d74ba5357aa4d7d7Selim Gurun#ifdef SSL_OP_NO_TLSv1_1
451fb292835997c64a14669de65d74ba5357aa4d7d7Selim Gurun  options.ConfigureFlag(SSL_OP_NO_TLSv1_1, true);
452fb292835997c64a14669de65d74ba5357aa4d7d7Selim Gurun#endif
453fb292835997c64a14669de65d74ba5357aa4d7d7Selim Gurun#ifdef SSL_OP_NO_TLSv1_2
454fb292835997c64a14669de65d74ba5357aa4d7d7Selim Gurun  options.ConfigureFlag(SSL_OP_NO_TLSv1_2, true);
455fb292835997c64a14669de65d74ba5357aa4d7d7Selim Gurun#endif
4568db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom
4578db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom#if defined(SSL_OP_NO_COMPRESSION)
4588db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom  // If TLS was disabled also disable compression, to provide maximum site
4598db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom  // compatibility in the case of protocol fallback. See http://crbug.com/31628
460de6c9f9aec5e2e7e66cb77140f7418fc29644ef0Selim Gurun#ifdef ANDROID
461de6c9f9aec5e2e7e66cb77140f7418fc29644ef0Selim Gurun  options.ConfigureFlag(SSL_OP_NO_COMPRESSION, true);
462de6c9f9aec5e2e7e66cb77140f7418fc29644ef0Selim Gurun#else
4638db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom  options.ConfigureFlag(SSL_OP_NO_COMPRESSION, !ssl_config_.tls1_enabled);
4648db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom#endif
465de6c9f9aec5e2e7e66cb77140f7418fc29644ef0Selim Gurun#endif
466731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
467731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // TODO(joth): Set this conditionally, see http://crbug.com/55410
4688db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom  options.ConfigureFlag(SSL_OP_LEGACY_SERVER_CONNECT, true);
4698db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom
4708db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom  SSL_set_options(ssl_, options.set_mask);
4718db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom  SSL_clear_options(ssl_, options.clear_mask);
47221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
47321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Same as above, this time for the SSL mode.
47421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  SslSetClearMask mode;
47521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
47621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#if defined(SSL_MODE_HANDSHAKE_CUTTHROUGH)
47721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  mode.ConfigureFlag(SSL_MODE_HANDSHAKE_CUTTHROUGH,
47821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                     ssl_config_.false_start_enabled &&
47921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                     !SSLConfigService::IsKnownFalseStartIncompatibleServer(
48021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                         host_and_port_.host()));
48121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#endif
48221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
48321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#if defined(SSL_MODE_RELEASE_BUFFERS)
48421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  mode.ConfigureFlag(SSL_MODE_RELEASE_BUFFERS, true);
48521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#endif
48621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
4878db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom#if defined(SSL_MODE_SMALL_BUFFERS)
4888db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom  mode.ConfigureFlag(SSL_MODE_SMALL_BUFFERS, true);
4898db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom#endif
490731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
4918db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom  SSL_set_mode(ssl_, mode.set_mask);
4928db08726a8eea9d32f637ced774aac6b16416071Brian Carlstrom  SSL_clear_mode(ssl_, mode.clear_mask);
49321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
49421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Removing ciphers by ID from OpenSSL is a bit involved as we must use the
49521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // textual name with SSL_set_cipher_list because there is no public API to
49621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // directly remove a cipher by ID.
49721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  STACK_OF(SSL_CIPHER)* ciphers = SSL_get_ciphers(ssl_);
49821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(ciphers);
49921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // See SSLConfig::disabled_cipher_suites for description of the suites
50021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // disabled by default.
50121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  std::string command("DEFAULT:!NULL:!aNULL:!IDEA:!FZA");
50221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Walk through all the installed ciphers, seeing if any need to be
50321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // appended to the cipher removal |command|.
50421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  for (int i = 0; i < sk_SSL_CIPHER_num(ciphers); ++i) {
50521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const SSL_CIPHER* cipher = sk_SSL_CIPHER_value(ciphers, i);
50621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const uint16 id = SSL_CIPHER_get_id(cipher);
50721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // Remove any ciphers with a strength of less than 80 bits. Note the NSS
50821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // implementation uses "effective" bits here but OpenSSL does not provide
50921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // this detail. This only impacts Triple DES: reports 112 vs. 168 bits,
51021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // both of which are greater than 80 anyway.
51121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    bool disable = SSL_CIPHER_get_bits(cipher, NULL) < 80;
51221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (!disable) {
51321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      disable = std::find(ssl_config_.disabled_cipher_suites.begin(),
51421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                          ssl_config_.disabled_cipher_suites.end(), id) !=
51521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                    ssl_config_.disabled_cipher_suites.end();
51621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
51721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (disable) {
51821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen       const char* name = SSL_CIPHER_get_name(cipher);
51921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen       DVLOG(3) << "Found cipher to remove: '" << name << "', ID: " << id
52021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                << " strength: " << SSL_CIPHER_get_bits(cipher, NULL);
52121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen       command.append(":!");
52221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen       command.append(name);
52321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen     }
52421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
52521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  int rv = SSL_set_cipher_list(ssl_, command.c_str());
52621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // If this fails (rv = 0) it means there are no ciphers enabled on this SSL.
52721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // This will almost certainly result in the socket failing to complete the
52821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // handshake at which point the appropriate error is bubbled up to the client.
52921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  LOG_IF(WARNING, rv != 1) << "SSL_set_cipher_list('" << command << "') "
53021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                              "returned " << rv;
531c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  return true;
532c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick}
53300d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
53421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenint SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl,
53521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                                      X509** x509,
53621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                                      EVP_PKEY** pkey) {
53721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DVLOG(3) << "OpenSSL ClientCertRequestCallback called";
53821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(ssl == ssl_);
53921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(*x509 == NULL);
54021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(*pkey == NULL);
54121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
54221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (!ssl_config_.send_client_cert) {
54321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    client_auth_cert_needed_ = true;
54421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return -1;  // Suspends handshake.
54521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
54621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
54721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Second pass: a client certificate should have been selected.
54821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (ssl_config_.client_cert) {
54921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    EVP_PKEY* privkey = OpenSSLPrivateKeyStore::GetInstance()->FetchPrivateKey(
55021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        X509_PUBKEY_get(X509_get_X509_PUBKEY(
55121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen            ssl_config_.client_cert->os_cert_handle())));
55221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (privkey) {
55388cd212725de4726b13b171fde17a47e2073ff2fBrian Carlstrom      CRYPTO_add(&privkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
55421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      // TODO(joth): (copied from NSS) We should wait for server certificate
55521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      // verification before sending our credentials. See http://crbug.com/13934
55621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      *x509 = X509Certificate::DupOSCertHandle(
55721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          ssl_config_.client_cert->os_cert_handle());
55821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      *pkey = privkey;
55921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      return 1;
56021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
56121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    LOG(WARNING) << "Client cert found without private key";
56221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
56321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
56421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Send no client certificate.
56521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return 0;
56621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
56721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
56800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch// SSLClientSocket methods
56900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
57000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdochvoid SSLClientSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) {
571c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  ssl_info->Reset();
572731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (!server_cert_)
573731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return;
574731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
575731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ssl_info->cert = server_cert_;
576731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ssl_info->cert_status = server_cert_verify_result_.cert_status;
577ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ssl_info->is_issued_by_known_root =
578ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      server_cert_verify_result_.is_issued_by_known_root;
579ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ssl_info->public_key_hashes =
580ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    server_cert_verify_result_.public_key_hashes;
581731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
582731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl_);
583731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  CHECK(cipher);
584731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  ssl_info->security_bits = SSL_CIPHER_get_bits(cipher, NULL);
585731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  const COMP_METHOD* compression = SSL_get_current_compression(ssl_);
58621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
58721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  ssl_info->connection_status = EncodeSSLConnectionStatus(
58821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      SSL_CIPHER_get_id(cipher),
58921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      compression ? compression->type : 0,
59021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      GetNetSSLVersion(ssl_));
591731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
592731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  bool peer_supports_renego_ext = !!SSL_get_secure_renegotiation_support(ssl_);
593731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (!peer_supports_renego_ext)
594731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    ssl_info->connection_status |= SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION;
59521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  UMA_HISTOGRAM_ENUMERATION("Net.RenegotiationExtensionSupported",
59621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                            implicit_cast<int>(peer_supports_renego_ext), 2);
597731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
598731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (ssl_config_.ssl3_fallback)
599731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    ssl_info->connection_status |= SSL_CONNECTION_SSL3_FALLBACK;
60021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
60121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DVLOG(3) << "Encoded connection status: cipher suite = "
60221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      << SSLConnectionStatusToCipherSuite(ssl_info->connection_status)
60321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      << " compression = "
60421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      << SSLConnectionStatusToCompression(ssl_info->connection_status)
60521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      << " version = "
60621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      << SSLConnectionStatusToVersion(ssl_info->connection_status);
60700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
60800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
60900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdochvoid SSLClientSocketOpenSSL::GetSSLCertRequestInfo(
61000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    SSLCertRequestInfo* cert_request_info) {
61121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  cert_request_info->host_and_port = host_and_port_.ToString();
61221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  cert_request_info->client_certs = client_certs_;
61300d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
61400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
615c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain MerrickSSLClientSocket::NextProtoStatus SSLClientSocketOpenSSL::GetNextProto(
616c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    std::string* proto) {
6170dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen  *proto = npn_proto_;
6180dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen  return npn_status_;
61900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
62000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
62100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdochvoid SSLClientSocketOpenSSL::DoReadCallback(int rv) {
62200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  // Since Run may result in Read being called, clear |user_read_callback_|
62300d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  // up front.
62400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  CompletionCallback* c = user_read_callback_;
62500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  user_read_callback_ = NULL;
62600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  user_read_buf_ = NULL;
62700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  user_read_buf_len_ = 0;
62800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  c->Run(rv);
62900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
63000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
63100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdochvoid SSLClientSocketOpenSSL::DoWriteCallback(int rv) {
63200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  // Since Run may result in Write being called, clear |user_write_callback_|
63300d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  // up front.
63400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  CompletionCallback* c = user_write_callback_;
63500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  user_write_callback_ = NULL;
63600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  user_write_buf_ = NULL;
63700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  user_write_buf_len_ = 0;
63800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  c->Run(rv);
63900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
64000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
64100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch// ClientSocket methods
64200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
6437b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#ifdef ANDROID
6447b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen// TODO(kristianm): handle the case when wait_for_connect is true
6457b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen// (sync requests)
6467b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#endif
6477b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsenint SSLClientSocketOpenSSL::Connect(CompletionCallback* callback
6487b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#ifdef ANDROID
6497b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen                                    , bool wait_for_connect
650e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma                                    , bool valid_uid
651e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma                                    , uid_t calling_uid
6527b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#endif
6537b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen                                   ) {
654c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT, NULL);
655c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick
656c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  // Set up new ssl object.
657c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  if (!Init()) {
65872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    int result = ERR_UNEXPECTED;
65972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, result);
66072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return result;
66100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  }
66200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
663c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  // Set SSL to client mode. Handshake happens in the loop below.
664c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  SSL_set_connect_state(ssl_);
66500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
66600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  GotoState(STATE_HANDSHAKE);
66700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  int rv = DoHandshakeLoop(net::OK);
66800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  if (rv == ERR_IO_PENDING) {
66900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    user_connect_callback_ = callback;
670c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  } else {
67172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
67200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  }
67300d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
67400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  return rv > OK ? OK : rv;
67500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
67600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
67700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdochvoid SSLClientSocketOpenSSL::Disconnect() {
678731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (ssl_) {
679731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    SSL_free(ssl_);
680731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    ssl_ = NULL;
681731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
682731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (transport_bio_) {
683731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    BIO_free_all(transport_bio_);
684731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    transport_bio_ = NULL;
685731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
686731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
687731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Shut down anything that may call us back (through buffer_send_callback_,
688731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // buffer_recv_callback, or handshake_io_callback_).
689731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  verifier_.reset();
690731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  transport_->socket()->Disconnect();
691731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
692c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  // Null all callbacks, delete all buffers.
693c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  transport_send_busy_ = false;
694c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  send_buffer_ = NULL;
695c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  transport_recv_busy_ = false;
696c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  recv_buffer_ = NULL;
697c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick
698c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  user_connect_callback_ = NULL;
699c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  user_read_callback_    = NULL;
700c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  user_write_callback_   = NULL;
701c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  user_read_buf_         = NULL;
702c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  user_read_buf_len_     = 0;
703c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  user_write_buf_        = NULL;
704c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  user_write_buf_len_    = 0;
705c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick
706731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  server_cert_verify_result_.Reset();
70700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  completed_handshake_ = false;
708201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
709201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  client_certs_.clear();
710201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  client_auth_cert_needed_ = false;
71100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
71200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
71300d26a728db2814620f390b418a7d6325ce5aca6Ben Murdochint SSLClientSocketOpenSSL::DoHandshakeLoop(int last_io_result) {
71400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  bool network_moved;
71500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  int rv = last_io_result;
71600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  do {
71700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    // Default to STATE_NONE for next state.
71800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    // (This is a quirk carried over from the windows
71900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    // implementation.  It makes reading the logs a bit harder.)
72000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    // State handlers can and often do call GotoState just
72100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    // to stay in the current state.
72200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    State state = next_handshake_state_;
72300d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    GotoState(STATE_NONE);
72400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    switch (state) {
72500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch      case STATE_NONE:
72600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch        // we're just pumping data between the buffer and the network
72700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch        break;
72800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch      case STATE_HANDSHAKE:
72900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch        rv = DoHandshake();
73000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch        break;
73100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch      case STATE_VERIFY_CERT:
732c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick        DCHECK(rv == OK);
733c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick        rv = DoVerifyCert(rv);
734c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick       break;
73500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch      case STATE_VERIFY_CERT_COMPLETE:
736c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick        rv = DoVerifyCertComplete(rv);
737c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick        break;
73800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch      default:
739c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick        rv = ERR_UNEXPECTED;
740c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick        NOTREACHED() << "unexpected state" << state;
74100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch        break;
74200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    }
74300d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
74400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    // To avoid getting an ERR_IO_PENDING here after handshake complete.
74500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    if (next_handshake_state_ == STATE_NONE)
74600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch      break;
74700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
748c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    // Do the actual network I/O.
74900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    network_moved = DoTransportIO();
75000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  } while ((rv != ERR_IO_PENDING || network_moved) &&
75100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch            next_handshake_state_ != STATE_NONE);
75200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  return rv;
75300d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
75400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
75500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdochint SSLClientSocketOpenSSL::DoHandshake() {
756ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
757c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  int net_error = net::OK;
758c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  int rv = SSL_do_handshake(ssl_);
75900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
76021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (client_auth_cert_needed_) {
76121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
76221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // If the handshake already succeeded (because the server requests but
76321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // doesn't require a client cert), we need to invalidate the SSL session
76421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // so that we won't try to resume the non-client-authenticated session in
76521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // the next handshake.  This will cause the server to ask for a client
76621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // cert again.
76721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (rv == 1) {
76821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      // Remove from session cache but don't clear this connection.
76921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      SSL_SESSION* session = SSL_get_session(ssl_);
77021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      if (session) {
77121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        int rv = SSL_CTX_remove_session(SSL_get_SSL_CTX(ssl_), session);
77221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        LOG_IF(WARNING, !rv) << "Couldn't invalidate SSL session: " << session;
77321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      }
77421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
77521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  } else if (rv == 1) {
776201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (trying_cached_session_ && logging::DEBUG_MODE) {
777201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      DVLOG(2) << "Result of session reuse for " << host_and_port_.ToString()
778201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch               << " is: " << (SSL_session_reused(ssl_) ? "Success" : "Fail");
779201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    }
78000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    // SSL handshake is completed.  Let's verify the certificate.
781731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    const bool got_cert = !!UpdateServerCert();
782731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    DCHECK(got_cert);
783731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    GotoState(STATE_VERIFY_CERT);
78400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  } else {
785c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    int ssl_error = SSL_get_error(ssl_, rv);
78621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    net_error = MapOpenSSLError(ssl_error, err_tracer);
78700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
78800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    // If not done, stay in this state
789731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (net_error == ERR_IO_PENDING) {
790731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      GotoState(STATE_HANDSHAKE);
791731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    } else {
792731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      LOG(ERROR) << "handshake failed; returned " << rv
793731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                 << ", SSL error code " << ssl_error
794731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                 << ", net_error " << net_error;
79521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      net_log_.AddEvent(
79621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          NetLog::TYPE_SSL_HANDSHAKE_ERROR,
79721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          make_scoped_refptr(new SSLErrorParams(net_error, ssl_error)));
798731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    }
79900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  }
800c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  return net_error;
80100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
80200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
8030dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsenint SSLClientSocketOpenSSL::SelectNextProtoCallback(unsigned char** out,
8040dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen                                                    unsigned char* outlen,
8050dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen                                                    const unsigned char* in,
8060dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen                                                    unsigned int inlen) {
8070dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen#if defined(OPENSSL_NPN_NEGOTIATED)
8080dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen  if (ssl_config_.next_protos.empty()) {
8090dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen    *out = reinterpret_cast<uint8*>(const_cast<char*>("http/1.1"));
8100dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen    *outlen = 8;
8110dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen    npn_status_ = SSLClientSocket::kNextProtoUnsupported;
8120dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen    return SSL_TLSEXT_ERR_OK;
8130dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen  }
8140dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen
8150dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen  int status = SSL_select_next_proto(
8160dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen      out, outlen, in, inlen,
8170dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen      reinterpret_cast<const unsigned char*>(ssl_config_.next_protos.data()),
8180dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen      ssl_config_.next_protos.size());
8190dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen
8200dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen  npn_proto_.assign(reinterpret_cast<const char*>(*out), *outlen);
8210dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen  switch (status) {
8220dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen    case OPENSSL_NPN_UNSUPPORTED:
8230dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen      npn_status_ = SSLClientSocket::kNextProtoUnsupported;
8240dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen      break;
8250dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen    case OPENSSL_NPN_NEGOTIATED:
8260dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen      npn_status_ = SSLClientSocket::kNextProtoNegotiated;
8270dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen      break;
8280dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen    case OPENSSL_NPN_NO_OVERLAP:
8290dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen      npn_status_ = SSLClientSocket::kNextProtoNoOverlap;
8300dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen      break;
8310dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen    default:
8320dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen      NOTREACHED() << status;
8330dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen      break;
8340dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen  }
83521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_;
83621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#endif
83721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return SSL_TLSEXT_ERR_OK;
83821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
8390dfd56d4192bd442742c9a0205590d7ef7b7f414Kristian Monsen
840731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickint SSLClientSocketOpenSSL::DoVerifyCert(int result) {
841731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(server_cert_);
842731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  GotoState(STATE_VERIFY_CERT_COMPLETE);
843731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  int flags = 0;
844731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
845731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (ssl_config_.rev_checking_enabled)
846731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED;
847731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (ssl_config_.verify_ev_cert)
848731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    flags |= X509Certificate::VERIFY_EV_CERT;
84921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  verifier_.reset(new SingleRequestCertVerifier(cert_verifier_));
8504a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  return verifier_->Verify(server_cert_, host_and_port_.host(), flags,
851731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                           &server_cert_verify_result_,
852731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                           &handshake_io_callback_);
853731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
854731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
855731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickint SSLClientSocketOpenSSL::DoVerifyCertComplete(int result) {
856731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  verifier_.reset();
857731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
858731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (result == OK) {
859731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // TODO(joth): Work out if we need to remember the intermediate CA certs
860731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // when the server sends them to us, and do so here.
861731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  } else {
862731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    DVLOG(1) << "DoVerifyCertComplete error " << ErrorToString(result)
863731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick             << " (" << result << ")";
864731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
865731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
866731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // If we have been explicitly told to accept this certificate, override the
867731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // result of verifier_.Verify.
868731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Eventually, we should cache the cert verification results so that we don't
869731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // need to call verifier_.Verify repeatedly.  But for now we need to do this.
870731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Alternatively, we could use the cert's status that we stored along with
871731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // the cert in the allowed_bad_certs vector.
872731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (IsCertificateError(result) &&
873731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      ssl_config_.IsAllowedBadCert(server_cert_)) {
874731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    VLOG(1) << "accepting bad SSL certificate, as user told us to";
875731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    result = OK;
876731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
877731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
878731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  completed_handshake_ = true;
879731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Exit DoHandshakeLoop and return the result to the caller to Connect.
880731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK_EQ(STATE_NONE, next_handshake_state_);
881731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return result;
882731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
883731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
884731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickX509Certificate* SSLClientSocketOpenSSL::UpdateServerCert() {
885731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (server_cert_)
886731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return server_cert_;
887731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
888ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  crypto::ScopedOpenSSL<X509, X509_free> cert(SSL_get_peer_certificate(ssl_));
889731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (!cert.get()) {
890731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    LOG(WARNING) << "SSL_get_peer_certificate returned NULL";
891731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return NULL;
892731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
893731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
894731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // Unlike SSL_get_peer_certificate, SSL_get_peer_cert_chain does not
895731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // increment the reference so sk_X509_free does not need to be called.
896731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl_);
897731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  X509Certificate::OSCertHandles intermediates;
898731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (chain) {
899731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    for (int i = 0; i < sk_X509_num(chain); ++i)
900731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      intermediates.push_back(sk_X509_value(chain, i));
901731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
902731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  server_cert_ = X509Certificate::CreateFromHandle(
903731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick      cert.get(), X509Certificate::SOURCE_FROM_NETWORK, intermediates);
904731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(server_cert_);
905731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
906731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return server_cert_;
907731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
908731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
90900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdochbool SSLClientSocketOpenSSL::DoTransportIO() {
91000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  bool network_moved = false;
91100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  int nsent = BufferSend();
91200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  int nreceived = BufferRecv();
91300d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  network_moved = (nsent > 0 || nreceived >= 0);
91400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  return network_moved;
91500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
91600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
91700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdochint SSLClientSocketOpenSSL::BufferSend(void) {
918c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  if (transport_send_busy_)
919c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    return ERR_IO_PENDING;
920c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick
921c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  if (!send_buffer_) {
922c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    // Get a fresh send buffer out of the send BIO.
923c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    size_t max_read = BIO_ctrl_pending(transport_bio_);
924c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    if (max_read > 0) {
925c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick      send_buffer_ = new DrainableIOBuffer(new IOBuffer(max_read), max_read);
926c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick      int read_bytes = BIO_read(transport_bio_, send_buffer_->data(), max_read);
927c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick      DCHECK_GT(read_bytes, 0);
928c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick      CHECK_EQ(static_cast<int>(max_read), read_bytes);
929c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    }
93000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  }
93100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
932c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  int rv = 0;
933c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  while (send_buffer_) {
934c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    rv = transport_->socket()->Write(send_buffer_,
935c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick                                     send_buffer_->BytesRemaining(),
936c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick                                     &buffer_send_callback_);
937c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    if (rv == ERR_IO_PENDING) {
938c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick      transport_send_busy_ = true;
939c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick      return rv;
940c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    }
941c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    TransportWriteComplete(rv);
94200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  }
943c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  return rv;
94400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
94500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
94600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdochvoid SSLClientSocketOpenSSL::BufferSendComplete(int result) {
94700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  transport_send_busy_ = false;
948c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  TransportWriteComplete(result);
94900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  OnSendComplete(result);
95000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
95100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
952c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrickvoid SSLClientSocketOpenSSL::TransportWriteComplete(int result) {
953731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(ERR_IO_PENDING != result);
954c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  if (result < 0) {
955c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    // Got a socket write error; close the BIO to indicate this upward.
956731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    DVLOG(1) << "TransportWriteComplete error " << result;
957c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    (void)BIO_shutdown_wr(transport_bio_);
958c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    send_buffer_ = NULL;
959c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  } else {
960c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    DCHECK(send_buffer_);
961c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    send_buffer_->DidConsume(result);
962c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    DCHECK_GE(send_buffer_->BytesRemaining(), 0);
963c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    if (send_buffer_->BytesRemaining() <= 0)
964c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick      send_buffer_ = NULL;
965c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  }
966c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick}
967c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick
96800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdochint SSLClientSocketOpenSSL::BufferRecv(void) {
96900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  if (transport_recv_busy_)
97000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    return ERR_IO_PENDING;
97100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
972c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  size_t max_write = BIO_ctrl_get_write_guarantee(transport_bio_);
973c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  if (max_write > kMaxRecvBufferSize)
974c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    max_write = kMaxRecvBufferSize;
975c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick
976c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  if (!max_write)
977c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    return ERR_IO_PENDING;
978c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick
979c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  recv_buffer_ = new IOBuffer(max_write);
980c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  int rv = transport_->socket()->Read(recv_buffer_, max_write,
981c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick                                      &buffer_recv_callback_);
982c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  if (rv == ERR_IO_PENDING) {
983c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    transport_recv_busy_ = true;
98400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  } else {
985c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    TransportReadComplete(rv);
98600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  }
98700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  return rv;
98800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
98900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
99000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdochvoid SSLClientSocketOpenSSL::BufferRecvComplete(int result) {
991c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  TransportReadComplete(result);
992c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  OnRecvComplete(result);
993c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick}
994c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick
995c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrickvoid SSLClientSocketOpenSSL::TransportReadComplete(int result) {
996731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(ERR_IO_PENDING != result);
997731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (result <= 0) {
998731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    DVLOG(1) << "TransportReadComplete result " << result;
999731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // Received 0 (end of file) or an error. Either way, bubble it up to the
1000731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // SSL layer via the BIO. TODO(joth): consider stashing the error code, to
1001731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    // relay up to the SSL socket client (i.e. via DoReadCallback).
1002731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    BIO_set_mem_eof_return(transport_bio_, 0);
1003731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    (void)BIO_shutdown_wr(transport_bio_);
1004731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  } else {
1005731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    DCHECK(recv_buffer_);
1006c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    int ret = BIO_write(transport_bio_, recv_buffer_->data(), result);
1007c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    // A write into a memory BIO should always succeed.
1008c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    CHECK_EQ(result, ret);
100900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  }
101000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  recv_buffer_ = NULL;
101100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  transport_recv_busy_ = false;
101200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
101300d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
101400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdochvoid SSLClientSocketOpenSSL::DoConnectCallback(int rv) {
101500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  CompletionCallback* c = user_connect_callback_;
101600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  user_connect_callback_ = NULL;
101700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  c->Run(rv > OK ? OK : rv);
101800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
101900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
102000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdochvoid SSLClientSocketOpenSSL::OnHandshakeIOComplete(int result) {
102100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  int rv = DoHandshakeLoop(result);
102200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  if (rv != ERR_IO_PENDING) {
102372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
102400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    DoConnectCallback(rv);
102500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  }
102600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
102700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
102800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdochvoid SSLClientSocketOpenSSL::OnSendComplete(int result) {
102900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  if (next_handshake_state_ != STATE_NONE) {
103000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    // In handshake phase.
103100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    OnHandshakeIOComplete(result);
103200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    return;
103300d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  }
103400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
103500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  // OnSendComplete may need to call DoPayloadRead while the renegotiation
103600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  // handshake is in progress.
103700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  int rv_read = ERR_IO_PENDING;
103800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  int rv_write = ERR_IO_PENDING;
103900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  bool network_moved;
104000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  do {
104100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch      if (user_read_buf_)
104200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch          rv_read = DoPayloadRead();
104300d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch      if (user_write_buf_)
104400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch          rv_write = DoPayloadWrite();
104500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch      network_moved = DoTransportIO();
104600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  } while (rv_read == ERR_IO_PENDING &&
104700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch           rv_write == ERR_IO_PENDING &&
104800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch           network_moved);
104900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
105000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  if (user_read_buf_ && rv_read != ERR_IO_PENDING)
105100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch      DoReadCallback(rv_read);
105200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  if (user_write_buf_ && rv_write != ERR_IO_PENDING)
105300d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch      DoWriteCallback(rv_write);
105400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
105500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
105600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdochvoid SSLClientSocketOpenSSL::OnRecvComplete(int result) {
105700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  if (next_handshake_state_ != STATE_NONE) {
105800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    // In handshake phase.
105900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    OnHandshakeIOComplete(result);
106000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    return;
106100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  }
106200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
106300d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  // Network layer received some data, check if client requested to read
106400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  // decrypted data.
1065c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  if (!user_read_buf_)
106600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    return;
106700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
106800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  int rv = DoReadLoop(result);
106900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  if (rv != ERR_IO_PENDING)
107000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    DoReadCallback(rv);
107100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
107200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
107300d26a728db2814620f390b418a7d6325ce5aca6Ben Murdochbool SSLClientSocketOpenSSL::IsConnected() const {
107400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  bool ret = completed_handshake_ && transport_->socket()->IsConnected();
107500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  return ret;
107600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
107700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
107800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdochbool SSLClientSocketOpenSSL::IsConnectedAndIdle() const {
107900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  bool ret = completed_handshake_ && transport_->socket()->IsConnectedAndIdle();
108000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  return ret;
108100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
108200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
108300d26a728db2814620f390b418a7d6325ce5aca6Ben Murdochint SSLClientSocketOpenSSL::GetPeerAddress(AddressList* addressList) const {
108400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  return transport_->socket()->GetPeerAddress(addressList);
108500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
108600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
1087ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint SSLClientSocketOpenSSL::GetLocalAddress(IPEndPoint* addressList) const {
1088ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return transport_->socket()->GetLocalAddress(addressList);
1089ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
1090ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
109100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdochconst BoundNetLog& SSLClientSocketOpenSSL::NetLog() const {
1092c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  return net_log_;
1093c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick}
1094c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick
1095c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrickvoid SSLClientSocketOpenSSL::SetSubresourceSpeculation() {
1096c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  if (transport_.get() && transport_->socket()) {
1097c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    transport_->socket()->SetSubresourceSpeculation();
1098c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  } else {
1099c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    NOTREACHED();
1100c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  }
1101c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick}
1102c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick
1103c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrickvoid SSLClientSocketOpenSSL::SetOmniboxSpeculation() {
1104c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  if (transport_.get() && transport_->socket()) {
1105c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    transport_->socket()->SetOmniboxSpeculation();
1106c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  } else {
1107c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    NOTREACHED();
1108c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  }
1109c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick}
1110c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick
1111c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrickbool SSLClientSocketOpenSSL::WasEverUsed() const {
1112c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  if (transport_.get() && transport_->socket())
1113c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick    return transport_->socket()->WasEverUsed();
1114c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick
1115c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  NOTREACHED();
1116c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  return false;
111700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
111800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
1119513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool SSLClientSocketOpenSSL::UsingTCPFastOpen() const {
1120513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (transport_.get() && transport_->socket())
1121513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return transport_->socket()->UsingTCPFastOpen();
1122513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
1123513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  NOTREACHED();
1124513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return false;
1125513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
1126513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
112700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch// Socket methods
112800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
1129c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrickint SSLClientSocketOpenSSL::Read(IOBuffer* buf,
1130c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick                                 int buf_len,
1131c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick                                 CompletionCallback* callback) {
113200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  user_read_buf_ = buf;
113300d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  user_read_buf_len_ = buf_len;
113400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
113500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  int rv = DoReadLoop(OK);
113600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
1137c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  if (rv == ERR_IO_PENDING) {
113800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    user_read_callback_ = callback;
1139c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  } else {
114000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    user_read_buf_ = NULL;
114100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    user_read_buf_len_ = 0;
114200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  }
114300d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
114400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  return rv;
114500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
114600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
114700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdochint SSLClientSocketOpenSSL::DoReadLoop(int result) {
114800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  if (result < 0)
114900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    return result;
115000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
115100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  bool network_moved;
115200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  int rv;
115300d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  do {
115400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    rv = DoPayloadRead();
115500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    network_moved = DoTransportIO();
115600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  } while (rv == ERR_IO_PENDING && network_moved);
115700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
115800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  return rv;
115900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
116000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
1161c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrickint SSLClientSocketOpenSSL::Write(IOBuffer* buf,
1162c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick                                  int buf_len,
1163c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick                                  CompletionCallback* callback) {
116400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  user_write_buf_ = buf;
116500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  user_write_buf_len_ = buf_len;
116600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
116700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  int rv = DoWriteLoop(OK);
116800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
1169c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  if (rv == ERR_IO_PENDING) {
117000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    user_write_callback_ = callback;
1171c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  } else {
117200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    user_write_buf_ = NULL;
117300d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    user_write_buf_len_ = 0;
117400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  }
117500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
117600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  return rv;
117700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
117800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
117900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdochint SSLClientSocketOpenSSL::DoWriteLoop(int result) {
118000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  if (result < 0)
118100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    return result;
118200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
118300d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  bool network_moved;
118400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  int rv;
118500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  do {
118600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    rv = DoPayloadWrite();
118700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    network_moved = DoTransportIO();
118800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  } while (rv == ERR_IO_PENDING && network_moved);
118900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
119000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch  return rv;
119100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
119200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
119300d26a728db2814620f390b418a7d6325ce5aca6Ben Murdochbool SSLClientSocketOpenSSL::SetReceiveBufferSize(int32 size) {
1194c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  return transport_->socket()->SetReceiveBufferSize(size);
119500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
119600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
119700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdochbool SSLClientSocketOpenSSL::SetSendBufferSize(int32 size) {
1198c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  return transport_->socket()->SetSendBufferSize(size);
119900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
120000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
120100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdochint SSLClientSocketOpenSSL::DoPayloadRead() {
1202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
1203c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  int rv = SSL_read(ssl_, user_read_buf_->data(), user_read_buf_len_);
1204c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  // We don't need to invalidate the non-client-authenticated SSL session
1205c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  // because the server will renegotiate anyway.
1206c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  if (client_auth_cert_needed_)
120700d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    return ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
120800d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
1209c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  if (rv >= 0)
121000d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    return rv;
121100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
1212c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  int err = SSL_get_error(ssl_, rv);
121321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return MapOpenSSLError(err, err_tracer);
121400d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
121500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
121600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdochint SSLClientSocketOpenSSL::DoPayloadWrite() {
1217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
1218c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_);
121900d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
1220c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  if (rv >= 0)
122100d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch    return rv;
122200d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
1223c6df357b0380597cd1c1b6d28fa7d8ecb98fbbd8Iain Merrick  int err = SSL_get_error(ssl_, rv);
122421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return MapOpenSSLError(err, err_tracer);
122500d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch}
122600d26a728db2814620f390b418a7d6325ce5aca6Ben Murdoch
122721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}  // namespace net
1228