diff options
author | byungchul@chromium.org <byungchul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-17 16:02:08 +0000 |
---|---|---|
committer | byungchul@chromium.org <byungchul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-17 16:02:08 +0000 |
commit | c8a80e99796678a7dca2c23111e03a593b9a7655 (patch) | |
tree | b57b15486e0796196d502b42184c92a1defd212e /net/socket/ssl_client_socket_openssl.cc | |
parent | 7ef5378569d945939649e1c4aede54eb39aaacda (diff) | |
download | chromium_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.cc | 180 |
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; |