summaryrefslogtreecommitdiffstats
path: root/net/socket/ssl_client_socket_openssl.cc
diff options
context:
space:
mode:
authorbyungchul@chromium.org <byungchul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-17 16:02:08 +0000
committerbyungchul@chromium.org <byungchul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-17 16:02:08 +0000
commitc8a80e99796678a7dca2c23111e03a593b9a7655 (patch)
treeb57b15486e0796196d502b42184c92a1defd212e /net/socket/ssl_client_socket_openssl.cc
parent7ef5378569d945939649e1c4aede54eb39aaacda (diff)
downloadchromium_src-c8a80e99796678a7dca2c23111e03a593b9a7655.zip
chromium_src-c8a80e99796678a7dca2c23111e03a593b9a7655.tar.gz
chromium_src-c8a80e99796678a7dca2c23111e03a593b9a7655.tar.bz2
Implement SSL server socket over OpenSSL.
1) Mixed ssl_server_socket_nss.cc and ssl_client_socket_openssl.cc. 2) Moved common functions into openssl_util.cc. 3) Enabled SslServerSocketTest when USE_OPENSSL is defined. BUG= Review URL: https://codereview.chromium.org/274783002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@271218 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/socket/ssl_client_socket_openssl.cc')
-rw-r--r--net/socket/ssl_client_socket_openssl.cc180
1 files changed, 17 insertions, 163 deletions
diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc
index d6345f7..35598d8 100644
--- a/net/socket/ssl_client_socket_openssl.cc
+++ b/net/socket/ssl_client_socket_openssl.cc
@@ -13,7 +13,6 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
-#include "base/debug/alias.h"
#include "base/memory/singleton.h"
#include "base/metrics/histogram.h"
#include "base/synchronization/lock.h"
@@ -23,6 +22,7 @@
#include "net/cert/cert_verifier.h"
#include "net/cert/single_request_cert_verifier.h"
#include "net/cert/x509_certificate_net_log_param.h"
+#include "net/socket/openssl_ssl_util.h"
#include "net/socket/ssl_error_params.h"
#include "net/socket/ssl_session_cache_openssl.h"
#include "net/ssl/openssl_client_key_store.h"
@@ -87,148 +87,6 @@ int GetNetSSLVersion(SSL* ssl) {
}
}
-int MapOpenSSLErrorSSL() {
- // Walk down the error stack to find the SSLerr generated reason.
- unsigned long error_code;
- do {
- error_code = ERR_get_error();
- if (error_code == 0)
- return ERR_SSL_PROTOCOL_ERROR;
- } while (ERR_GET_LIB(error_code) != ERR_LIB_SSL);
-
- DVLOG(1) << "OpenSSL SSL error, reason: " << ERR_GET_REASON(error_code)
- << ", name: " << ERR_error_string(error_code, NULL);
- switch (ERR_GET_REASON(error_code)) {
- case SSL_R_READ_TIMEOUT_EXPIRED:
- return ERR_TIMED_OUT;
- case SSL_R_BAD_RESPONSE_ARGUMENT:
- return ERR_INVALID_ARGUMENT;
- case SSL_R_UNKNOWN_CERTIFICATE_TYPE:
- case SSL_R_UNKNOWN_CIPHER_TYPE:
- case SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE:
- case SSL_R_UNKNOWN_PKEY_TYPE:
- case SSL_R_UNKNOWN_REMOTE_ERROR_TYPE:
- case SSL_R_UNKNOWN_SSL_VERSION:
- return ERR_NOT_IMPLEMENTED;
- case SSL_R_UNSUPPORTED_SSL_VERSION:
- case SSL_R_NO_CIPHER_MATCH:
- case SSL_R_NO_SHARED_CIPHER:
- case SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY:
- case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION:
- case SSL_R_UNSUPPORTED_PROTOCOL:
- return ERR_SSL_VERSION_OR_CIPHER_MISMATCH;
- case SSL_R_SSLV3_ALERT_BAD_CERTIFICATE:
- case SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE:
- case SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED:
- case SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED:
- case SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN:
- case SSL_R_TLSV1_ALERT_ACCESS_DENIED:
- case SSL_R_TLSV1_ALERT_UNKNOWN_CA:
- return ERR_BAD_SSL_CLIENT_AUTH_CERT;
- case SSL_R_BAD_DECOMPRESSION:
- case SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE:
- return ERR_SSL_DECOMPRESSION_FAILURE_ALERT;
- case SSL_R_SSLV3_ALERT_BAD_RECORD_MAC:
- return ERR_SSL_BAD_RECORD_MAC_ALERT;
- case SSL_R_TLSV1_ALERT_DECRYPT_ERROR:
- return ERR_SSL_DECRYPT_ERROR_ALERT;
- case SSL_R_TLSV1_UNRECOGNIZED_NAME:
- return ERR_SSL_UNRECOGNIZED_NAME_ALERT;
- case SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED:
- return ERR_SSL_UNSAFE_NEGOTIATION;
- case SSL_R_WRONG_NUMBER_OF_KEY_BITS:
- return ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY;
- // SSL_R_UNKNOWN_PROTOCOL is reported if premature application data is
- // received (see http://crbug.com/42538), and also if all the protocol
- // versions supported by the server were disabled in this socket instance.
- // Mapped to ERR_SSL_PROTOCOL_ERROR for compatibility with other SSL sockets
- // in the former scenario.
- case SSL_R_UNKNOWN_PROTOCOL:
- case SSL_R_SSL_HANDSHAKE_FAILURE:
- case SSL_R_DECRYPTION_FAILED:
- case SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC:
- case SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG:
- case SSL_R_DIGEST_CHECK_FAILED:
- case SSL_R_DUPLICATE_COMPRESSION_ID:
- case SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER:
- case SSL_R_ENCRYPTED_LENGTH_TOO_LONG:
- case SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST:
- case SSL_R_EXCESSIVE_MESSAGE_SIZE:
- case SSL_R_EXTRA_DATA_IN_MESSAGE:
- case SSL_R_GOT_A_FIN_BEFORE_A_CCS:
- case SSL_R_ILLEGAL_PADDING:
- case SSL_R_INVALID_CHALLENGE_LENGTH:
- case SSL_R_INVALID_COMMAND:
- case SSL_R_INVALID_PURPOSE:
- case SSL_R_INVALID_STATUS_RESPONSE:
- case SSL_R_INVALID_TICKET_KEYS_LENGTH:
- case SSL_R_KEY_ARG_TOO_LONG:
- case SSL_R_READ_WRONG_PACKET_TYPE:
- // SSL_do_handshake reports this error when the server responds to a
- // ClientHello with a fatal close_notify alert.
- case SSL_AD_REASON_OFFSET + SSL_AD_CLOSE_NOTIFY:
- case SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE:
- // TODO(joth): SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE may be returned from the
- // server after receiving ClientHello if there's no common supported cipher.
- // Ideally we'd map that specific case to ERR_SSL_VERSION_OR_CIPHER_MISMATCH
- // to match the NSS implementation. See also http://goo.gl/oMtZW
- case SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE:
- case SSL_R_SSLV3_ALERT_NO_CERTIFICATE:
- case SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER:
- case SSL_R_TLSV1_ALERT_DECODE_ERROR:
- case SSL_R_TLSV1_ALERT_DECRYPTION_FAILED:
- case SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION:
- case SSL_R_TLSV1_ALERT_INTERNAL_ERROR:
- case SSL_R_TLSV1_ALERT_NO_RENEGOTIATION:
- case SSL_R_TLSV1_ALERT_RECORD_OVERFLOW:
- case SSL_R_TLSV1_ALERT_USER_CANCELLED:
- return ERR_SSL_PROTOCOL_ERROR;
- case SSL_R_CERTIFICATE_VERIFY_FAILED:
- // The only way that the certificate verify callback can fail is if
- // the leaf certificate changed during a renegotiation.
- return ERR_SSL_SERVER_CERT_CHANGED;
- default:
- LOG(WARNING) << "Unmapped error reason: " << ERR_GET_REASON(error_code);
- return ERR_FAILED;
- }
-}
-
-// Converts an OpenSSL error code into a net error code, walking the OpenSSL
-// error stack if needed. Note that |tracer| is not currently used in the
-// implementation, but is passed in anyway as this ensures the caller will clear
-// any residual codes left on the error stack.
-int MapOpenSSLError(int err, const crypto::OpenSSLErrStackTracer& tracer) {
- switch (err) {
- case SSL_ERROR_WANT_READ:
- case SSL_ERROR_WANT_WRITE:
- return ERR_IO_PENDING;
- case SSL_ERROR_SYSCALL:
- LOG(ERROR) << "OpenSSL SYSCALL error, earliest error code in "
- "error queue: " << ERR_peek_error() << ", errno: "
- << errno;
- return ERR_SSL_PROTOCOL_ERROR;
- case SSL_ERROR_SSL:
- return MapOpenSSLErrorSSL();
- default:
- // TODO(joth): Implement full mapping.
- LOG(WARNING) << "Unknown OpenSSL error " << err;
- return ERR_SSL_PROTOCOL_ERROR;
- }
-}
-
-// Utility to construct the appropriate set & clear masks for use the OpenSSL
-// options and mode configuration functions. (SSL_set_options etc)
-struct SslSetClearMask {
- SslSetClearMask() : set_mask(0), clear_mask(0) {}
- void ConfigureFlag(long flag, bool state) {
- (state ? set_mask : clear_mask) |= flag;
- // Make sure we haven't got any intersection in the set & clear options.
- DCHECK_EQ(0, set_mask & clear_mask) << flag << ":" << state;
- }
- long set_mask;
- long clear_mask;
-};
-
// Compute a unique key string for the SSL session cache. |socket| is an
// input socket object. Return a string.
std::string GetSocketSessionCacheKey(const SSLClientSocketOpenSSL& socket) {
@@ -533,11 +391,9 @@ int SSLClientSocketOpenSSL::ExportKeyingMaterial(
crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
int rv = SSL_export_keying_material(
- ssl_, out, outlen, const_cast<char*>(label.data()),
- label.size(),
- reinterpret_cast<unsigned char*>(const_cast<char*>(context.data())),
- context.length(),
- context.length() > 0);
+ ssl_, out, outlen, label.data(), label.size(),
+ reinterpret_cast<const unsigned char*>(context.data()),
+ context.length(), context.length() > 0);
if (rv != 1) {
int ssl_error = SSL_get_error(ssl_, rv);
@@ -550,6 +406,7 @@ int SSLClientSocketOpenSSL::ExportKeyingMaterial(
}
int SSLClientSocketOpenSSL::GetTLSUniqueChannelBinding(std::string* out) {
+ NOTIMPLEMENTED();
return ERR_NOT_IMPLEMENTED;
}
@@ -557,17 +414,17 @@ int SSLClientSocketOpenSSL::Connect(const CompletionCallback& callback) {
net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT);
// Set up new ssl object.
- if (!Init()) {
- int result = ERR_UNEXPECTED;
- net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, result);
- return result;
+ int rv = Init();
+ if (rv != OK) {
+ net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
+ return rv;
}
// Set SSL to client mode. Handshake happens in the loop below.
SSL_set_connect_state(ssl_);
GotoState(STATE_HANDSHAKE);
- int rv = DoHandshakeLoop(net::OK);
+ rv = DoHandshakeLoop(OK);
if (rv == ERR_IO_PENDING) {
user_connect_callback_ = callback;
} else {
@@ -784,7 +641,7 @@ int SSLClientSocketOpenSSL::SetSendBufferSize(int32 size) {
return transport_->socket()->SetSendBufferSize(size);
}
-bool SSLClientSocketOpenSSL::Init() {
+int SSLClientSocketOpenSSL::Init() {
DCHECK(!ssl_);
DCHECK(!transport_bio_);
@@ -793,10 +650,10 @@ bool SSLClientSocketOpenSSL::Init() {
ssl_ = SSL_new(context->ssl_ctx());
if (!ssl_ || !context->SetClientSocketForSSL(ssl_, this))
- return false;
+ return ERR_UNEXPECTED;
if (!SSL_set_tlsext_host_name(ssl_, host_and_port_.host().c_str()))
- return false;
+ return ERR_UNEXPECTED;
trying_cached_session_ = context->session_cache()->SetSSLSessionWithKey(
ssl_, GetSocketSessionCacheKey(*this));
@@ -804,7 +661,7 @@ bool SSLClientSocketOpenSSL::Init() {
BIO* ssl_bio = NULL;
// 0 => use default buffer sizes.
if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0))
- return false;
+ return ERR_UNEXPECTED;
DCHECK(ssl_bio);
DCHECK(transport_bio_);
@@ -893,7 +750,7 @@ bool SSLClientSocketOpenSSL::Init() {
SSL_enable_tls_channel_id(ssl_);
}
- return true;
+ return OK;
}
void SSLClientSocketOpenSSL::DoReadCallback(int rv) {
@@ -933,7 +790,7 @@ bool SSLClientSocketOpenSSL::DoTransportIO() {
int SSLClientSocketOpenSSL::DoHandshake() {
crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
- int net_error = net::OK;
+ int net_error = OK;
int rv = SSL_do_handshake(ssl_);
if (client_auth_cert_needed_) {
@@ -1393,10 +1250,7 @@ int SSLClientSocketOpenSSL::TransportReadComplete(int result) {
DCHECK(recv_buffer_.get());
int ret = BIO_write(transport_bio_, recv_buffer_->data(), result);
// A write into a memory BIO should always succeed.
- // Force values on the stack for http://crbug.com/335557
- base::debug::Alias(&result);
- base::debug::Alias(&ret);
- CHECK_EQ(result, ret);
+ DCHECK_EQ(result, ret);
}
recv_buffer_ = NULL;
transport_recv_busy_ = false;