15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OpenSSL binding for SSLClientSocket. The class layout and general principle
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of operation is derived from SSLClientSocketNSS.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/ssl_client_socket_openssl.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <openssl/err.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <openssl/opensslv.h>
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <openssl/ssl.h>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/callback_helpers.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/openssl_util.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/cert_verifier.h"
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/single_request_cert_verifier.h"
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_certificate_net_log_param.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/ssl_error_params.h"
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/ssl/openssl_client_key_store.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/ssl/ssl_cert_request_info.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/ssl/ssl_connection_status_flags.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/ssl/ssl_info.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Enable this to see logging for state machine state transitions.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GotoState(s) do { DVLOG(2) << (void *)this << " " << __FUNCTION__ << \
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           " jump to state " << s; \
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           next_handshake_state_ = s; } while (0)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GotoState(s) next_handshake_state_ = s
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kSessionCacheTimeoutSeconds = 60 * 60;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kSessionCacheMaxEntires = 1024;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This constant can be any non-negative/non-zero value (eg: it does not
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// overlap with any value of the net::Error range, including net::OK).
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kNoPendingReadResult = 1;
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If a client doesn't have a list of protocols that it supports, but
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the server supports NPN, choosing "http/1.1" is the best answer.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kDefaultSupportedNPNProtocol[] = "http/1.1";
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if OPENSSL_VERSION_NUMBER < 0x1000103fL
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This method doesn't seem to have made it into the OpenSSL headers.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned long SSL_CIPHER_get_id(const SSL_CIPHER* cipher) { return cipher->id; }
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Used for encoding the |connection_status| field of an SSLInfo object.
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int EncodeSSLConnectionStatus(int cipher_suite,
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              int compression,
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              int version) {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ((cipher_suite & SSL_CONNECTION_CIPHERSUITE_MASK) <<
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SSL_CONNECTION_CIPHERSUITE_SHIFT) |
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         ((compression & SSL_CONNECTION_COMPRESSION_MASK) <<
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SSL_CONNECTION_COMPRESSION_SHIFT) |
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         ((version & SSL_CONNECTION_VERSION_MASK) <<
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          SSL_CONNECTION_VERSION_SHIFT);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the net SSL version number (see ssl_connection_status_flags.h) for
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this SSL connection.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int GetNetSSLVersion(SSL* ssl) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (SSL_version(ssl)) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL2_VERSION:
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SSL_CONNECTION_VERSION_SSL2;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL3_VERSION:
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SSL_CONNECTION_VERSION_SSL3;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case TLS1_VERSION:
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SSL_CONNECTION_VERSION_TLS1;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 0x0302:
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SSL_CONNECTION_VERSION_TLS1_1;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 0x0303:
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SSL_CONNECTION_VERSION_TLS1_2;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SSL_CONNECTION_VERSION_UNKNOWN;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MapOpenSSLErrorSSL() {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Walk down the error stack to find the SSLerr generated reason.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned long error_code;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error_code = ERR_get_error();
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (error_code == 0)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_SSL_PROTOCOL_ERROR;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (ERR_GET_LIB(error_code) != ERR_LIB_SSL);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "OpenSSL SSL error, reason: " << ERR_GET_REASON(error_code)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << ", name: " << ERR_error_string(error_code, NULL);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (ERR_GET_REASON(error_code)) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_READ_TIMEOUT_EXPIRED:
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_TIMED_OUT;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_BAD_RESPONSE_ARGUMENT:
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_INVALID_ARGUMENT;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_UNKNOWN_CERTIFICATE_TYPE:
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_UNKNOWN_CIPHER_TYPE:
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE:
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_UNKNOWN_PKEY_TYPE:
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_UNKNOWN_REMOTE_ERROR_TYPE:
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_UNKNOWN_SSL_VERSION:
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_NOT_IMPLEMENTED;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_UNSUPPORTED_SSL_VERSION:
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_NO_CIPHER_MATCH:
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_NO_SHARED_CIPHER:
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY:
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION:
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case SSL_R_UNSUPPORTED_PROTOCOL:
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_SSL_VERSION_OR_CIPHER_MISMATCH;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_SSLV3_ALERT_BAD_CERTIFICATE:
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE:
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED:
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED:
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN:
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_TLSV1_ALERT_ACCESS_DENIED:
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_TLSV1_ALERT_UNKNOWN_CA:
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_BAD_SSL_CLIENT_AUTH_CERT;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_BAD_DECOMPRESSION:
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE:
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_SSL_DECOMPRESSION_FAILURE_ALERT;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_SSLV3_ALERT_BAD_RECORD_MAC:
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_SSL_BAD_RECORD_MAC_ALERT;
1337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case SSL_R_TLSV1_ALERT_DECRYPT_ERROR:
1347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return ERR_SSL_DECRYPT_ERROR_ALERT;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED:
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_SSL_UNSAFE_NEGOTIATION;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_WRONG_NUMBER_OF_KEY_BITS:
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SSL_R_UNKNOWN_PROTOCOL is reported if premature application data is
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // received (see http://crbug.com/42538), and also if all the protocol
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // versions supported by the server were disabled in this socket instance.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Mapped to ERR_SSL_PROTOCOL_ERROR for compatibility with other SSL sockets
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // in the former scenario.
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_UNKNOWN_PROTOCOL:
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_SSL_HANDSHAKE_FAILURE:
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_DECRYPTION_FAILED:
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC:
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG:
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_DIGEST_CHECK_FAILED:
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_DUPLICATE_COMPRESSION_ID:
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER:
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_ENCRYPTED_LENGTH_TOO_LONG:
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST:
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_EXCESSIVE_MESSAGE_SIZE:
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_EXTRA_DATA_IN_MESSAGE:
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_GOT_A_FIN_BEFORE_A_CCS:
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_ILLEGAL_PADDING:
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_INVALID_CHALLENGE_LENGTH:
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_INVALID_COMMAND:
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_INVALID_PURPOSE:
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_INVALID_STATUS_RESPONSE:
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_INVALID_TICKET_KEYS_LENGTH:
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_KEY_ARG_TOO_LONG:
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_READ_WRONG_PACKET_TYPE:
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE:
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(joth): SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE may be returned from the
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // server after receiving ClientHello if there's no common supported cipher.
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Ideally we'd map that specific case to ERR_SSL_VERSION_OR_CIPHER_MISMATCH
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to match the NSS implementation. See also http://goo.gl/oMtZW
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE:
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_SSLV3_ALERT_NO_CERTIFICATE:
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER:
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_TLSV1_ALERT_DECODE_ERROR:
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_TLSV1_ALERT_DECRYPTION_FAILED:
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION:
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_TLSV1_ALERT_INTERNAL_ERROR:
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_TLSV1_ALERT_NO_RENEGOTIATION:
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_TLSV1_ALERT_RECORD_OVERFLOW:
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_R_TLSV1_ALERT_USER_CANCELLED:
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_SSL_PROTOCOL_ERROR;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Unmapped error reason: " << ERR_GET_REASON(error_code);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_FAILED;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts an OpenSSL error code into a net error code, walking the OpenSSL
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// error stack if needed. Note that |tracer| is not currently used in the
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// implementation, but is passed in anyway as this ensures the caller will clear
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// any residual codes left on the error stack.
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MapOpenSSLError(int err, const crypto::OpenSSLErrStackTracer& tracer) {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (err) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_ERROR_WANT_READ:
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_ERROR_WANT_WRITE:
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_IO_PENDING;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_ERROR_SYSCALL:
197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      LOG(ERROR) << "OpenSSL SYSCALL error, earliest error code in "
198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                    "error queue: " << ERR_peek_error() << ", errno: "
199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                 << errno;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_SSL_PROTOCOL_ERROR;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case SSL_ERROR_SSL:
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return MapOpenSSLErrorSSL();
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // TODO(joth): Implement full mapping.
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "Unknown OpenSSL error " << err;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_SSL_PROTOCOL_ERROR;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We do certificate verification after handshake, so we disable the default
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// by registering a no-op verify function.
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int NoOpVerifyCallback(X509_STORE_CTX*, void *) {
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(3) << "skipping cert verify";
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 1;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OpenSSL manages a cache of SSL_SESSION, this class provides the application
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// side policy for that cache about session re-use: we retain one session per
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// unique HostPortPair, per shard.
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SSLSessionCache {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLSessionCache() {}
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnSessionAdded(const HostPortPair& host_and_port,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      const std::string& shard,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      SSL_SESSION* session) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Declare the session cleaner-upper before the lock, so any call into
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // OpenSSL to free the session will happen after the lock is released.
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    crypto::ScopedOpenSSL<SSL_SESSION, SSL_SESSION_free> session_to_free;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock lock(lock_);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(0U, session_map_.count(session));
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string cache_key = GetCacheKey(host_and_port, shard);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::pair<HostPortMap::iterator, bool> res =
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        host_port_map_.insert(std::make_pair(cache_key, session));
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!res.second) {  // Already exists: replace old entry.
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session_to_free.reset(res.first->second);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      session_map_.erase(session_to_free.get());
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      res.first->second = session;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(2) << "Adding session " << session << " => "
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << cache_key << ", new entry = " << res.second;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(host_port_map_[cache_key] == session);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    session_map_[session] = res.first;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(host_port_map_.size(), session_map_.size());
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_LE(host_port_map_.size(), kSessionCacheMaxEntires);
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnSessionRemoved(SSL_SESSION* session) {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Declare the session cleaner-upper before the lock, so any call into
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // OpenSSL to free the session will happen after the lock is released.
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    crypto::ScopedOpenSSL<SSL_SESSION, SSL_SESSION_free> session_to_free;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock lock(lock_);
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SessionMap::iterator it = session_map_.find(session);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (it == session_map_.end())
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(2) << "Remove session " << session << " => " << it->second->first;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(it->second->second == session);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host_port_map_.erase(it->second);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    session_map_.erase(it);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    session_to_free.reset(session);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(host_port_map_.size(), session_map_.size());
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Looks up the host:port in the cache, and if a session is found it is added
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to |ssl|, returning true on success.
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool SetSSLSession(SSL* ssl, const HostPortPair& host_and_port,
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const std::string& shard) {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::AutoLock lock(lock_);
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string cache_key = GetCacheKey(host_and_port, shard);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HostPortMap::iterator it = host_port_map_.find(cache_key);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (it == host_port_map_.end())
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(2) << "Lookup session: " << it->second << " => " << cache_key;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_SESSION* session = it->second;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(session);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(session_map_[session] == it);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Ideally we'd release |lock_| before calling into OpenSSL here, however
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // that opens a small risk |session| will go out of scope before it is used.
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Alternatively we would take a temporary local refcount on |session|,
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // except OpenSSL does not provide a public API for adding a ref (c.f.
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SSL_SESSION_free which decrements the ref).
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SSL_set_session(ssl, session) == 1;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Flush removes all entries from the cache. This is called when a client
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // certificate is added.
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void Flush() {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (HostPortMap::iterator i = host_port_map_.begin();
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         i != host_port_map_.end(); i++) {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SSL_SESSION_free(i->second);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host_port_map_.clear();
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    session_map_.clear();
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static std::string GetCacheKey(const HostPortPair& host_and_port,
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const std::string& shard) {
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return host_and_port.ToString() + "/" + shard;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A pair of maps to allow bi-directional lookups between host:port and an
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // associated session.
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::map<std::string, SSL_SESSION*> HostPortMap;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::map<SSL_SESSION*, HostPortMap::iterator> SessionMap;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HostPortMap host_port_map_;
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SessionMap session_map_;
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Protects access to both the above maps.
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::Lock lock_;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SSLSessionCache);
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SSLContext {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static SSLContext* GetInstance() { return Singleton<SSLContext>::get(); }
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL_CTX* ssl_ctx() { return ssl_ctx_.get(); }
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLSessionCache* session_cache() { return &session_cache_; }
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLClientSocketOpenSSL* GetClientSocketFromSSL(SSL* ssl) {
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(ssl);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSLClientSocketOpenSSL* socket = static_cast<SSLClientSocketOpenSSL*>(
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        SSL_get_ex_data(ssl, ssl_socket_data_index_));
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(socket);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return socket;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool SetClientSocketForSSL(SSL* ssl, SSLClientSocketOpenSSL* socket) {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SSL_set_ex_data(ssl, ssl_socket_data_index_, socket) != 0;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend struct DefaultSingletonTraits<SSLContext>;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLContext() {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    crypto::EnsureOpenSSLInit();
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_NE(ssl_socket_data_index_, -1);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_ctx_.reset(SSL_CTX_new(SSLv23_client_method()));
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), NoOpVerifyCallback, NULL);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_CTX_set_session_cache_mode(ssl_ctx_.get(), SSL_SESS_CACHE_CLIENT);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_CTX_sess_set_new_cb(ssl_ctx_.get(), NewSessionCallbackStatic);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_CTX_sess_set_remove_cb(ssl_ctx_.get(), RemoveSessionCallbackStatic);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_CTX_set_timeout(ssl_ctx_.get(), kSessionCacheTimeoutSeconds);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_CTX_sess_set_cache_size(ssl_ctx_.get(), kSessionCacheMaxEntires);
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_CTX_set_client_cert_cb(ssl_ctx_.get(), ClientCertCallback);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OPENSSL_NPN_NEGOTIATED)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(kristianm): Only select this if ssl_config_.next_proto is not empty.
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // It would be better if the callback were not a global setting,
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // but that is an OpenSSL issue.
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_CTX_set_next_proto_select_cb(ssl_ctx_.get(), SelectNextProtoCallback,
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     NULL);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static int NewSessionCallbackStatic(SSL* ssl, SSL_SESSION* session) {
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GetInstance()->NewSessionCallback(ssl, session);
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int NewSessionCallback(SSL* ssl, SSL_SESSION* session) {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSLClientSocketOpenSSL* socket = GetClientSocketFromSSL(ssl);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    session_cache_.OnSessionAdded(socket->host_and_port(),
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  socket->ssl_session_cache_shard(),
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  session);
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 1;  // 1 => We took ownership of |session|.
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void RemoveSessionCallbackStatic(SSL_CTX* ctx, SSL_SESSION* session) {
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GetInstance()->RemoveSessionCallback(ctx, session);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RemoveSessionCallback(SSL_CTX* ctx, SSL_SESSION* session) {
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(ctx == ssl_ctx());
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    session_cache_.OnSessionRemoved(session);
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static int ClientCertCallback(SSL* ssl, X509** x509, EVP_PKEY** pkey) {
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl);
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(socket);
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return socket->ClientCertRequestCallback(ssl, x509, pkey);
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static int SelectNextProtoCallback(SSL* ssl,
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     unsigned char** out, unsigned char* outlen,
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const unsigned char* in,
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     unsigned int inlen, void* arg) {
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl);
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return socket->SelectNextProtoCallback(out, outlen, in, inlen);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is the index used with SSL_get_ex_data to retrieve the owner
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SSLClientSocketOpenSSL object from an SSL instance.
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ssl_socket_data_index_;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // session_cache_ must appear before |ssl_ctx_| because the destruction of
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |ssl_ctx_| may trigger callbacks into |session_cache_|. Therefore,
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |session_cache_| must be destructed after |ssl_ctx_|.
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLSessionCache session_cache_;
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  crypto::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Utility to construct the appropriate set & clear masks for use the OpenSSL
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// options and mode configuration functions. (SSL_set_options etc)
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct SslSetClearMask {
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SslSetClearMask() : set_mask(0), clear_mask(0) {}
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ConfigureFlag(long flag, bool state) {
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (state ? set_mask : clear_mask) |= flag;
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make sure we haven't got any intersection in the set & clear options.
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(0, set_mask & clear_mask) << flag << ":" << state;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  long set_mask;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  long clear_mask;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocket::ClearSessionCache() {
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLContext* context = SSLContext::GetInstance();
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  context->session_cache()->Flush();
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientSocketOpenSSL::SSLClientSocketOpenSSL(
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ClientSocketHandle* transport_socket,
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HostPortPair& host_and_port,
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SSLConfig& ssl_config,
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SSLClientSocketContext& context)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : transport_send_busy_(false),
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_recv_busy_(false),
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_recv_eof_(false),
435a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      weak_factory_(this),
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pending_read_error_(kNoPendingReadResult),
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      completed_handshake_(false),
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      client_auth_cert_needed_(false),
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cert_verifier_(context.cert_verifier),
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_(NULL),
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_bio_(NULL),
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_(transport_socket),
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      host_and_port_(host_and_port),
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_config_(ssl_config),
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_session_cache_shard_(context.ssl_session_cache_shard),
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      trying_cached_session_(false),
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_handshake_state_(STATE_NONE),
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      npn_status_(kNextProtoUnsupported),
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_(transport_socket->socket()->NetLog()) {
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() {
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Disconnect();
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketOpenSSL::Init() {
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!ssl_);
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!transport_bio_);
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLContext* context = SSLContext::GetInstance();
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_ = SSL_new(context->ssl_ctx());
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ssl_ || !context->SetClientSocketForSSL(ssl_, this))
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!SSL_set_tlsext_host_name(ssl_, host_and_port_.host().c_str()))
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  trying_cached_session_ =
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context->session_cache()->SetSSLSession(ssl_, host_and_port_,
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              ssl_session_cache_shard_);
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BIO* ssl_bio = NULL;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 0 => use default buffer sizes.
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0))
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(ssl_bio);
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(transport_bio_);
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL_set_bio(ssl_, ssl_bio, ssl_bio);
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OpenSSL defaults some options to on, others to off. To avoid ambiguity,
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // set everything we care about to an absolute value.
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SslSetClearMask options;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.ConfigureFlag(SSL_OP_NO_SSLv2, true);
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ssl3_enabled = (ssl_config_.version_min == SSL_PROTOCOL_VERSION_SSL3);
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.ConfigureFlag(SSL_OP_NO_SSLv3, !ssl3_enabled);
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool tls1_enabled = (ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1 &&
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1);
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.ConfigureFlag(SSL_OP_NO_TLSv1, !tls1_enabled);
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(SSL_OP_NO_TLSv1_1)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool tls1_1_enabled =
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1_1 &&
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1_1);
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.ConfigureFlag(SSL_OP_NO_TLSv1_1, !tls1_1_enabled);
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(SSL_OP_NO_TLSv1_2)
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool tls1_2_enabled =
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1_2 &&
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1_2);
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.ConfigureFlag(SSL_OP_NO_TLSv1_2, !tls1_2_enabled);
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(SSL_OP_NO_COMPRESSION)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.ConfigureFlag(SSL_OP_NO_COMPRESSION, true);
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(joth): Set this conditionally, see http://crbug.com/55410
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  options.ConfigureFlag(SSL_OP_LEGACY_SERVER_CONNECT, true);
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL_set_options(ssl_, options.set_mask);
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL_clear_options(ssl_, options.clear_mask);
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Same as above, this time for the SSL mode.
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SslSetClearMask mode;
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(SSL_MODE_RELEASE_BUFFERS)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mode.ConfigureFlag(SSL_MODE_RELEASE_BUFFERS, true);
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(SSL_MODE_SMALL_BUFFERS)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mode.ConfigureFlag(SSL_MODE_SMALL_BUFFERS, true);
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL_set_mode(ssl_, mode.set_mask);
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL_clear_mode(ssl_, mode.clear_mask);
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Removing ciphers by ID from OpenSSL is a bit involved as we must use the
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // textual name with SSL_set_cipher_list because there is no public API to
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // directly remove a cipher by ID.
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STACK_OF(SSL_CIPHER)* ciphers = SSL_get_ciphers(ssl_);
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(ciphers);
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See SSLConfig::disabled_cipher_suites for description of the suites
535eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // disabled by default. Note that !SHA384 only removes HMAC-SHA384 cipher
536eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // suites, not GCM cipher suites with SHA384 as the handshake hash.
537eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string command("DEFAULT:!NULL:!aNULL:!IDEA:!FZA:!SRP:!SHA384:!aECDH");
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Walk through all the installed ciphers, seeing if any need to be
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // appended to the cipher removal |command|.
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < sk_SSL_CIPHER_num(ciphers); ++i) {
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SSL_CIPHER* cipher = sk_SSL_CIPHER_value(ciphers, i);
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const uint16 id = SSL_CIPHER_get_id(cipher);
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Remove any ciphers with a strength of less than 80 bits. Note the NSS
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // implementation uses "effective" bits here but OpenSSL does not provide
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // this detail. This only impacts Triple DES: reports 112 vs. 168 bits,
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // both of which are greater than 80 anyway.
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool disable = SSL_CIPHER_get_bits(cipher, NULL) < 80;
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!disable) {
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      disable = std::find(ssl_config_.disabled_cipher_suites.begin(),
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          ssl_config_.disabled_cipher_suites.end(), id) !=
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ssl_config_.disabled_cipher_suites.end();
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (disable) {
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       const char* name = SSL_CIPHER_get_name(cipher);
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       DVLOG(3) << "Found cipher to remove: '" << name << "', ID: " << id
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                << " strength: " << SSL_CIPHER_get_bits(cipher, NULL);
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       command.append(":!");
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       command.append(name);
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     }
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = SSL_set_cipher_list(ssl_, command.c_str());
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If this fails (rv = 0) it means there are no ciphers enabled on this SSL.
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This will almost certainly result in the socket failing to complete the
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // handshake at which point the appropriate error is bubbled up to the client.
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG_IF(WARNING, rv != 1) << "SSL_set_cipher_list('" << command << "') "
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              "returned " << rv;
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl,
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                      X509** x509,
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                      EVP_PKEY** pkey) {
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(3) << "OpenSSL ClientCertRequestCallback called";
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(ssl == ssl_);
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(*x509 == NULL);
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(*pkey == NULL);
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ssl_config_.send_client_cert) {
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // First pass: we know that a client certificate is needed, but we do not
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // have one at hand.
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    client_auth_cert_needed_ = true;
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    STACK_OF(X509_NAME) *authorities = SSL_get_client_CA_list(ssl);
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int i = 0; i < sk_X509_NAME_num(authorities); i++) {
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      X509_NAME *ca_name = (X509_NAME *)sk_X509_NAME_value(authorities, i);
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      unsigned char* str = NULL;
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int length = i2d_X509_NAME(ca_name, &str);
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      cert_authorities_.push_back(std::string(
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          reinterpret_cast<const char*>(str),
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          static_cast<size_t>(length)));
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      OPENSSL_free(str);
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;  // Suspends handshake.
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Second pass: a client certificate should have been selected.
5977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (ssl_config_.client_cert.get()) {
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // A note about ownership: FetchClientCertPrivateKey() increments
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // the reference count of the EVP_PKEY. Ownership of this reference
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // is passed directly to OpenSSL, which will release the reference
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // using EVP_PKEY_free() when the SSL object is destroyed.
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    OpenSSLClientKeyStore::ScopedEVP_PKEY privkey;
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (OpenSSLClientKeyStore::GetInstance()->FetchClientCertPrivateKey(
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            ssl_config_.client_cert.get(), &privkey)) {
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // TODO(joth): (copied from NSS) We should wait for server certificate
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // verification before sending our credentials. See http://crbug.com/13934
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *x509 = X509Certificate::DupOSCertHandle(
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ssl_config_.client_cert->os_cert_handle());
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *pkey = privkey.release();
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 1;
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "Client cert found without private key";
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Send no client certificate.
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SSLClientSocket methods
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) {
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->Reset();
6237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!server_cert_.get())
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->cert = server_cert_verify_result_.verified_cert;
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->cert_status = server_cert_verify_result_.cert_status;
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->is_issued_by_known_root =
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      server_cert_verify_result_.is_issued_by_known_root;
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->public_key_hashes =
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_cert_verify_result_.public_key_hashes;
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->client_cert_sent =
6337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      ssl_config_.send_client_cert && ssl_config_.client_cert.get();
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->channel_id_sent = WasChannelIDSent();
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl_);
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(cipher);
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->security_bits = SSL_CIPHER_get_bits(cipher, NULL);
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const COMP_METHOD* compression = SSL_get_current_compression(ssl_);
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_info->connection_status = EncodeSSLConnectionStatus(
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SSL_CIPHER_get_id(cipher),
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      compression ? compression->type : 0,
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetNetSSLVersion(ssl_));
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool peer_supports_renego_ext = !!SSL_get_secure_renegotiation_support(ssl_);
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!peer_supports_renego_ext)
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_info->connection_status |= SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION;
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("Net.RenegotiationExtensionSupported",
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            implicit_cast<int>(peer_supports_renego_ext), 2);
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_config_.version_fallback)
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_info->connection_status |= SSL_CONNECTION_VERSION_FALLBACK;
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ssl_info->handshake_type = SSL_session_reused(ssl_) ?
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SSLInfo::HANDSHAKE_RESUME : SSLInfo::HANDSHAKE_FULL;
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(3) << "Encoded connection status: cipher suite = "
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << SSLConnectionStatusToCipherSuite(ssl_info->connection_status)
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << " version = "
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << SSLConnectionStatusToVersion(ssl_info->connection_status);
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::GetSSLCertRequestInfo(
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSLCertRequestInfo* cert_request_info) {
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cert_request_info->host_and_port = host_and_port_.ToString();
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  cert_request_info->cert_authorities = cert_authorities_;
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::ExportKeyingMaterial(
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::StringPiece& label,
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool has_context, const base::StringPiece& context,
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned char* out, unsigned int outlen) {
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = SSL_export_keying_material(
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_, out, outlen, const_cast<char*>(label.data()),
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      label.size(),
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<unsigned char*>(const_cast<char*>(context.data())),
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context.length(),
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context.length() > 0);
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != 1) {
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ssl_error = SSL_get_error(ssl_, rv);
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to export keying material;"
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << " returned " << rv
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << ", SSL error code " << ssl_error;
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return MapOpenSSLError(ssl_error, err_tracer);
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::GetTLSUniqueChannelBinding(std::string* out) {
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ERR_NOT_IMPLEMENTED;
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientSocket::NextProtoStatus SSLClientSocketOpenSSL::GetNextProto(
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string* proto, std::string* server_protos) {
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *proto = npn_proto_;
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *server_protos = server_protos_;
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return npn_status_;
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ServerBoundCertService*
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientSocketOpenSSL::GetServerBoundCertService() const {
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::DoReadCallback(int rv) {
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since Run may result in Read being called, clear |user_read_callback_|
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // up front.
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_read_buf_ = NULL;
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_read_buf_len_ = 0;
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ResetAndReturn(&user_read_callback_).Run(rv);
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::DoWriteCallback(int rv) {
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since Run may result in Write being called, clear |user_write_callback_|
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // up front.
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_write_buf_ = NULL;
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_write_buf_len_ = 0;
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ResetAndReturn(&user_write_callback_).Run(rv);
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// StreamSocket implementation.
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::Connect(const CompletionCallback& callback) {
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT);
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set up new ssl object.
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Init()) {
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int result = ERR_UNEXPECTED;
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, result);
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set SSL to client mode. Handshake happens in the loop below.
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSL_set_connect_state(ssl_);
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GotoState(STATE_HANDSHAKE);
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoHandshakeLoop(net::OK);
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_connect_callback_ = callback;
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv > OK ? OK : rv;
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::Disconnect() {
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_) {
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Calling SSL_shutdown prevents the session from being marked as
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // unresumable.
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_shutdown(ssl_);
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_free(ssl_);
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_ = NULL;
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_bio_) {
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BIO_free_all(transport_bio_);
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transport_bio_ = NULL;
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Shut down anything that may call us back.
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  verifier_.reset();
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transport_->socket()->Disconnect();
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Null all callbacks, delete all buffers.
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transport_send_busy_ = false;
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  send_buffer_ = NULL;
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transport_recv_busy_ = false;
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transport_recv_eof_ = false;
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  recv_buffer_ = NULL;
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_connect_callback_.Reset();
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_read_callback_.Reset();
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_write_callback_.Reset();
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_read_buf_         = NULL;
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_read_buf_len_     = 0;
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_write_buf_        = NULL;
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_write_buf_len_    = 0;
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server_cert_verify_result_.Reset();
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  completed_handshake_ = false;
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  cert_authorities_.clear();
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  client_auth_cert_needed_ = false;
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::DoHandshakeLoop(int last_io_result) {
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = last_io_result;
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Default to STATE_NONE for next state.
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // (This is a quirk carried over from the windows
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // implementation.  It makes reading the logs a bit harder.)
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // State handlers can and often do call GotoState just
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to stay in the current state.
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    State state = next_handshake_state_;
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GotoState(STATE_NONE);
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (state) {
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_HANDSHAKE:
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoHandshake();
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_VERIFY_CERT:
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK(rv == OK);
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoVerifyCert(rv);
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       break;
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_VERIFY_CERT_COMPLETE:
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoVerifyCertComplete(rv);
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_NONE:
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = ERR_UNEXPECTED;
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED() << "unexpected state" << state;
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool network_moved = DoTransportIO();
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (network_moved && next_handshake_state_ == STATE_HANDSHAKE) {
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // In general we exit the loop if rv is ERR_IO_PENDING.  In this
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // special case we keep looping even if rv is ERR_IO_PENDING because
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the transport IO may allow DoHandshake to make progress.
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = OK;  // This causes us to stay in the loop.
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::DoHandshake() {
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int net_error = net::OK;
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = SSL_do_handshake(ssl_);
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (client_auth_cert_needed_) {
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If the handshake already succeeded (because the server requests but
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // doesn't require a client cert), we need to invalidate the SSL session
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // so that we won't try to resume the non-client-authenticated session in
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the next handshake.  This will cause the server to ask for a client
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // cert again.
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == 1) {
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Remove from session cache but don't clear this connection.
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SSL_SESSION* session = SSL_get_session(ssl_);
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (session) {
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int rv = SSL_CTX_remove_session(SSL_get_SSL_CTX(ssl_), session);
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG_IF(WARNING, !rv) << "Couldn't invalidate SSL session: " << session;
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (rv == 1) {
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (trying_cached_session_ && logging::DEBUG_MODE) {
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DVLOG(2) << "Result of session reuse for " << host_and_port_.ToString()
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << " is: " << (SSL_session_reused(ssl_) ? "Success" : "Fail");
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SSL handshake is completed.  Let's verify the certificate.
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const bool got_cert = !!UpdateServerCert();
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(got_cert);
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.AddEvent(
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NetLog::TYPE_SSL_CERTIFICATES_RECEIVED,
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&NetLogX509CertificateCallback,
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   base::Unretained(server_cert_.get())));
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GotoState(STATE_VERIFY_CERT);
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ssl_error = SSL_get_error(ssl_, rv);
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_error = MapOpenSSLError(ssl_error, err_tracer);
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If not done, stay in this state
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (net_error == ERR_IO_PENDING) {
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GotoState(STATE_HANDSHAKE);
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "handshake failed; returned " << rv
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << ", SSL error code " << ssl_error
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << ", net_error " << net_error;
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_.AddEvent(
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NetLog::TYPE_SSL_HANDSHAKE_ERROR,
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CreateNetLogSSLErrorCallback(net_error, ssl_error));
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net_error;
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SelectNextProtoCallback is called by OpenSSL during the handshake. If the
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// server supports NPN, selects a protocol from the list that the server
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// provides. According to third_party/openssl/openssl/ssl/ssl_lib.c, the
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// callback can assume that |in| is syntactically valid.
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::SelectNextProtoCallback(unsigned char** out,
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    unsigned char* outlen,
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    const unsigned char* in,
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    unsigned int inlen) {
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OPENSSL_NPN_NEGOTIATED)
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_config_.next_protos.empty()) {
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *out = reinterpret_cast<uint8*>(
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const_cast<char*>(kDefaultSupportedNPNProtocol));
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *outlen = arraysize(kDefaultSupportedNPNProtocol) - 1;
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    npn_status_ = kNextProtoUnsupported;
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SSL_TLSEXT_ERR_OK;
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Assume there's no overlap between our protocols and the server's list.
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  npn_status_ = kNextProtoNoOverlap;
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For each protocol in server preference order, see if we support it.
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned int i = 0; i < inlen; i += in[i] + 1) {
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (std::vector<std::string>::const_iterator
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             j = ssl_config_.next_protos.begin();
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         j != ssl_config_.next_protos.end(); ++j) {
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (in[i] == j->size() &&
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          memcmp(&in[i + 1], j->data(), in[i]) == 0) {
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We found a match.
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *out = const_cast<unsigned char*>(in) + i + 1;
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *outlen = in[i];
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        npn_status_ = kNextProtoNegotiated;
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (npn_status_ == kNextProtoNegotiated)
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we didn't find a protocol, we select the first one from our list.
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (npn_status_ == kNextProtoNoOverlap) {
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *out = reinterpret_cast<uint8*>(const_cast<char*>(
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ssl_config_.next_protos[0].data()));
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *outlen = ssl_config_.next_protos[0].size();
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  npn_proto_.assign(reinterpret_cast<const char*>(*out), *outlen);
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server_protos_.assign(reinterpret_cast<const char*>(in), inlen);
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_;
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SSL_TLSEXT_ERR_OK;
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::DoVerifyCert(int result) {
9347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(server_cert_.get());
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GotoState(STATE_VERIFY_CERT_COMPLETE);
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CertStatus cert_status;
9387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (ssl_config_.IsAllowedBadCert(server_cert_.get(), &cert_status)) {
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Received an expected bad cert with status: " << cert_status;
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_cert_verify_result_.Reset();
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_cert_verify_result_.cert_status = cert_status;
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    server_cert_verify_result_.verified_cert = server_cert_;
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags = 0;
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_config_.rev_checking_enabled)
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flags |= CertVerifier::VERIFY_REV_CHECKING_ENABLED;
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_config_.verify_ev_cert)
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flags |= CertVerifier::VERIFY_EV_CERT;
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_config_.cert_io_enabled)
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flags |= CertVerifier::VERIFY_CERT_IO_ENABLED;
953558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (ssl_config_.rev_checking_required_local_anchors)
954558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    flags |= CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS;
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  verifier_.reset(new SingleRequestCertVerifier(cert_verifier_));
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return verifier_->Verify(
9577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      server_cert_.get(),
9587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      host_and_port_.host(),
9597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      flags,
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NULL /* no CRL set */,
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &server_cert_verify_result_,
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&SSLClientSocketOpenSSL::OnHandshakeIOComplete,
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)),
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_);
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::DoVerifyCertComplete(int result) {
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  verifier_.reset();
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == OK) {
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(joth): Work out if we need to remember the intermediate CA certs
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // when the server sends them to us, and do so here.
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "DoVerifyCertComplete error " << ErrorToString(result)
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << " (" << result << ")";
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  completed_handshake_ = true;
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Exit DoHandshakeLoop and return the result to the caller to Connect.
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_handshake_state_);
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X509Certificate* SSLClientSocketOpenSSL::UpdateServerCert() {
9857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (server_cert_.get())
9867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return server_cert_.get();
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  crypto::ScopedOpenSSL<X509, X509_free> cert(SSL_get_peer_certificate(ssl_));
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cert.get()) {
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "SSL_get_peer_certificate returned NULL";
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Unlike SSL_get_peer_certificate, SSL_get_peer_cert_chain does not
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // increment the reference so sk_X509_free does not need to be called.
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl_);
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  X509Certificate::OSCertHandles intermediates;
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (chain) {
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < sk_X509_num(chain); ++i)
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      intermediates.push_back(sk_X509_value(chain, i));
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server_cert_ = X509Certificate::CreateFromHandle(cert.get(), intermediates);
10037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(server_cert_.get());
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return server_cert_.get();
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketOpenSSL::DoTransportIO() {
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool network_moved = false;
1010b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  int rv;
1011b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Read and write as much data as possible. The loop is necessary because
1012b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Write() may return synchronously.
1013b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  do {
1014b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    rv = BufferSend();
1015b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (rv != ERR_IO_PENDING && rv != 0)
1016b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      network_moved = true;
1017b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  } while (rv > 0);
1018b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!transport_recv_eof_ && BufferRecv() != ERR_IO_PENDING)
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    network_moved = true;
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return network_moved;
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::BufferSend(void) {
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_send_busy_)
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!send_buffer_.get()) {
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Get a fresh send buffer out of the send BIO.
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t max_read = BIO_ctrl_pending(transport_bio_);
1030b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (!max_read)
1031b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      return 0;  // Nothing pending in the OpenSSL write BIO.
1032b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    send_buffer_ = new DrainableIOBuffer(new IOBuffer(max_read), max_read);
1033b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    int read_bytes = BIO_read(transport_bio_, send_buffer_->data(), max_read);
1034b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    DCHECK_GT(read_bytes, 0);
1035b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    CHECK_EQ(static_cast<int>(max_read), read_bytes);
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1038b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  int rv = transport_->socket()->Write(
10397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      send_buffer_.get(),
10407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      send_buffer_->BytesRemaining(),
10417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      base::Bind(&SSLClientSocketOpenSSL::BufferSendComplete,
10427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                 base::Unretained(this)));
1043b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (rv == ERR_IO_PENDING) {
1044b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    transport_send_busy_ = true;
1045b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  } else {
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransportWriteComplete(rv);
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::BufferSendComplete(int result) {
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transport_send_busy_ = false;
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransportWriteComplete(result);
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnSendComplete(result);
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::TransportWriteComplete(int result) {
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(ERR_IO_PENDING != result);
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result < 0) {
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Got a socket write error; close the BIO to indicate this upward.
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "TransportWriteComplete error " << result;
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (void)BIO_shutdown_wr(transport_bio_);
1063a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    BIO_set_mem_eof_return(transport_bio_, 0);
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    send_buffer_ = NULL;
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
10667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    DCHECK(send_buffer_.get());
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    send_buffer_->DidConsume(result);
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_GE(send_buffer_->BytesRemaining(), 0);
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (send_buffer_->BytesRemaining() <= 0)
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      send_buffer_ = NULL;
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::BufferRecv(void) {
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_recv_busy_)
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Determine how much was requested from |transport_bio_| that was not
10792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // actually available.
10802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t requested = BIO_ctrl_get_read_request(transport_bio_);
10812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (requested == 0) {
10822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // This is not a perfect match of error codes, as no operation is
10832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // actually pending. However, returning 0 would be interpreted as
10842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // a possible sign of EOF, which is also an inappropriate match.
10852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return ERR_IO_PENDING;
10862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Known Issue: While only reading |requested| data is the more correct
10892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // implementation, it has the downside of resulting in frequent reads:
10902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // One read for the SSL record header (~5 bytes) and one read for the SSL
10912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // record body. Rather than issuing these reads to the underlying socket
10922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // (and constantly allocating new IOBuffers), a single Read() request to
10932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // fill |transport_bio_| is issued. As long as an SSL client socket cannot
10942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // be gracefully shutdown (via SSL close alerts) and re-used for non-SSL
10952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // traffic, this over-subscribed Read()ing will not cause issues.
10962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t max_write = BIO_ctrl_get_write_guarantee(transport_bio_);
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!max_write)
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  recv_buffer_ = new IOBuffer(max_write);
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = transport_->socket()->Read(
11027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      recv_buffer_.get(),
11037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      max_write,
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&SSLClientSocketOpenSSL::BufferRecvComplete,
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transport_recv_busy_ = true;
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TransportReadComplete(rv);
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::BufferRecvComplete(int result) {
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransportReadComplete(result);
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnRecvComplete(result);
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::TransportReadComplete(int result) {
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(ERR_IO_PENDING != result);
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result <= 0) {
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "TransportReadComplete result " << result;
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Received 0 (end of file) or an error. Either way, bubble it up to the
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SSL layer via the BIO. TODO(joth): consider stashing the error code, to
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // relay up to the SSL socket client (i.e. via DoReadCallback).
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result == 0)
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_recv_eof_ = true;
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BIO_set_mem_eof_return(transport_bio_, 0);
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (void)BIO_shutdown_wr(transport_bio_);
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
11317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    DCHECK(recv_buffer_.get());
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int ret = BIO_write(transport_bio_, recv_buffer_->data(), result);
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // A write into a memory BIO should always succeed.
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK_EQ(result, ret);
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  recv_buffer_ = NULL;
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transport_recv_busy_ = false;
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::DoConnectCallback(int rv) {
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!user_connect_callback_.is_null()) {
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CompletionCallback c = user_connect_callback_;
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_connect_callback_.Reset();
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c.Run(rv > OK ? OK : rv);
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::OnHandshakeIOComplete(int result) {
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoHandshakeLoop(result);
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING) {
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoConnectCallback(rv);
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::OnSendComplete(int result) {
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (next_handshake_state_ == STATE_HANDSHAKE) {
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In handshake phase.
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnHandshakeIOComplete(result);
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OnSendComplete may need to call DoPayloadRead while the renegotiation
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // handshake is in progress.
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv_read = ERR_IO_PENDING;
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv_write = ERR_IO_PENDING;
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool network_moved;
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
11697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (user_read_buf_.get())
11707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      rv_read = DoPayloadRead();
11717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (user_write_buf_.get())
11727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      rv_write = DoPayloadWrite();
11737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    network_moved = DoTransportIO();
11747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  } while (rv_read == ERR_IO_PENDING && rv_write == ERR_IO_PENDING &&
11757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)           (user_read_buf_.get() || user_write_buf_.get()) && network_moved);
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1177a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Performing the Read callback may cause |this| to be deleted. If this
1178a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // happens, the Write callback should not be invoked. Guard against this by
1179a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // holding a WeakPtr to |this| and ensuring it's still valid.
1180a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  base::WeakPtr<SSLClientSocketOpenSSL> guard(weak_factory_.GetWeakPtr());
11817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (user_read_buf_.get() && rv_read != ERR_IO_PENDING)
11827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    DoReadCallback(rv_read);
1183a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1184a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (!guard.get())
1185a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return;
1186a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
11877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (user_write_buf_.get() && rv_write != ERR_IO_PENDING)
11887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    DoWriteCallback(rv_write);
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::OnRecvComplete(int result) {
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (next_handshake_state_ == STATE_HANDSHAKE) {
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In handshake phase.
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnHandshakeIOComplete(result);
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Network layer received some data, check if client requested to read
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // decrypted data.
12007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!user_read_buf_.get())
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoReadLoop(result);
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING)
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoReadCallback(rv);
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketOpenSSL::IsConnected() const {
12092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If the handshake has not yet completed.
12102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!completed_handshake_)
12112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
12122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If an asynchronous operation is still pending.
12137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (user_read_buf_.get() || user_write_buf_.get())
12142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
12152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return transport_->socket()->IsConnected();
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketOpenSSL::IsConnectedAndIdle() const {
12202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If the handshake has not yet completed.
12212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!completed_handshake_)
12222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
12232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If an asynchronous operation is still pending.
12247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (user_read_buf_.get() || user_write_buf_.get())
12252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
12262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If there is data waiting to be sent, or data read from the network that
12272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // has not yet been consumed.
12282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (BIO_ctrl_pending(transport_bio_) > 0 ||
12292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      BIO_ctrl_wpending(transport_bio_) > 0) {
12302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
12312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
12322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return transport_->socket()->IsConnectedAndIdle();
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::GetPeerAddress(IPEndPoint* addressList) const {
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_->socket()->GetPeerAddress(addressList);
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::GetLocalAddress(IPEndPoint* addressList) const {
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_->socket()->GetLocalAddress(addressList);
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BoundNetLog& SSLClientSocketOpenSSL::NetLog() const {
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net_log_;
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::SetSubresourceSpeculation() {
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_.get() && transport_->socket()) {
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transport_->socket()->SetSubresourceSpeculation();
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::SetOmniboxSpeculation() {
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_.get() && transport_->socket()) {
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transport_->socket()->SetOmniboxSpeculation();
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketOpenSSL::WasEverUsed() const {
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_.get() && transport_->socket())
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return transport_->socket()->WasEverUsed();
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketOpenSSL::UsingTCPFastOpen() const {
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_.get() && transport_->socket())
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return transport_->socket()->UsingTCPFastOpen();
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Socket methods
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::Read(IOBuffer* buf,
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 int buf_len,
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const CompletionCallback& callback) {
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_read_buf_ = buf;
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_read_buf_len_ = buf_len;
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoReadLoop(OK);
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_read_callback_ = callback;
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_read_buf_ = NULL;
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_read_buf_len_ = 0;
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::DoReadLoop(int result) {
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result < 0)
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool network_moved;
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = DoPayloadRead();
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    network_moved = DoTransportIO();
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv == ERR_IO_PENDING && network_moved);
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::Write(IOBuffer* buf,
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  int buf_len,
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const CompletionCallback& callback) {
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_write_buf_ = buf;
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_write_buf_len_ = buf_len;
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoWriteLoop(OK);
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_write_callback_ = callback;
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_write_buf_ = NULL;
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_write_buf_len_ = 0;
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::DoWriteLoop(int result) {
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result < 0)
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool network_moved;
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = DoPayloadWrite();
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    network_moved = DoTransportIO();
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv == ERR_IO_PENDING && network_moved);
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketOpenSSL::SetReceiveBufferSize(int32 size) {
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_->socket()->SetReceiveBufferSize(size);
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketOpenSSL::SetSendBufferSize(int32 size) {
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_->socket()->SetSendBufferSize(size);
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::DoPayloadRead() {
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
13562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int rv;
13582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (pending_read_error_ != kNoPendingReadResult) {
13592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rv = pending_read_error_;
13602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pending_read_error_ = kNoPendingReadResult;
13612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (rv == 0) {
13622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED,
13632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    rv, user_read_buf_->data());
13642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
13652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return rv;
13662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
13672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int total_bytes_read = 0;
13692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  do {
13702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rv = SSL_read(ssl_, user_read_buf_->data() + total_bytes_read,
13712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  user_read_buf_len_ - total_bytes_read);
13722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (rv > 0)
13732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      total_bytes_read += rv;
13742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } while (total_bytes_read < user_read_buf_len_ && rv > 0);
13752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (total_bytes_read == user_read_buf_len_) {
13772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rv = total_bytes_read;
13782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
13792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Otherwise, an error occurred (rv <= 0). The error needs to be handled
13802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // immediately, while the OpenSSL errors are still available in
13812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // thread-local storage. However, the handled/remapped error code should
13822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // only be returned if no application data was already read; if it was, the
13832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // error code should be deferred until the next call of DoPayloadRead.
13842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    //
13852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If no data was read, |*next_result| will point to the return value of
13862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // this function. If at least some data was read, |*next_result| will point
13872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // to |pending_read_error_|, to be returned in a future call to
13882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // DoPayloadRead() (e.g.: after the current data is handled).
13892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int *next_result = &rv;
13902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (total_bytes_read > 0) {
13912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      pending_read_error_ = rv;
13922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      rv = total_bytes_read;
13932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      next_result = &pending_read_error_;
13942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
13952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (client_auth_cert_needed_) {
13972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *next_result = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
13982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else if (*next_result < 0) {
13992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int err = SSL_get_error(ssl_, *next_result);
14002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      *next_result = MapOpenSSLError(err, err_tracer);
14012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (rv > 0 && *next_result == ERR_IO_PENDING) {
14022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // If at least some data was read from SSL_read(), do not treat
14032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // insufficient data as an error to return in the next call to
14042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // DoPayloadRead() - instead, let the call fall through to check
14052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // SSL_read() again. This is because DoTransportIO() may complete
14062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // in between the next call to DoPayloadRead(), and thus it is
14072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // important to check SSL_read() on subsequent invocations to see
14082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // if a complete record may now be read.
14092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        *next_result = kNoPendingReadResult;
14102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
14112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
14122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv >= 0) {
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv,
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  user_read_buf_->data());
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return rv;
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::DoPayloadWrite() {
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_);
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv >= 0) {
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_SENT, rv,
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  user_write_buf_->data());
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int err = SSL_get_error(ssl_, rv);
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return MapOpenSSLError(err, err_tracer);
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
1436