blob: d308e4c2b3d209808972c8b34a19b54e442664a7 [file] [log] [blame]
[email protected]013c17c2012-01-21 19:09:011// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]d518cd92010-09-29 12:27:442// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// OpenSSL binding for SSLClientSocket. The class layout and general principle
6// of operation is derived from SSLClientSocketNSS.
7
8#include "net/socket/ssl_client_socket_openssl.h"
9
10#include <openssl/ssl.h>
11#include <openssl/err.h>
12
[email protected]0f7804ec2011-10-07 20:04:1813#include "base/bind.h"
[email protected]3b63f8f42011-03-28 01:54:1514#include "base/memory/singleton.h"
[email protected]835d7c82010-10-14 04:38:3815#include "base/metrics/histogram.h"
[email protected]20305ec2011-01-21 04:55:5216#include "base/synchronization/lock.h"
[email protected]4b559b4d2011-04-14 17:37:1417#include "crypto/openssl_util.h"
[email protected]313834722010-11-17 09:57:1818#include "net/base/cert_verifier.h"
[email protected]d518cd92010-09-29 12:27:4419#include "net/base/net_errors.h"
[email protected]0c6523f2010-12-10 10:56:2420#include "net/base/openssl_private_key_store.h"
[email protected]718c9672010-12-02 10:04:1021#include "net/base/ssl_cert_request_info.h"
[email protected]d518cd92010-09-29 12:27:4422#include "net/base/ssl_connection_status_flags.h"
23#include "net/base/ssl_info.h"
[email protected]59468382011-11-04 02:22:0424#include "net/base/x509_certificate_net_log_param.h"
[email protected]109805a2010-12-07 18:17:0625#include "net/socket/ssl_error_params.h"
[email protected]d518cd92010-09-29 12:27:4426
27namespace net {
28
29namespace {
30
31// Enable this to see logging for state machine state transitions.
32#if 0
[email protected]3b112772010-10-04 10:54:4933#define GotoState(s) do { DVLOG(2) << (void *)this << " " << __FUNCTION__ << \
[email protected]d518cd92010-09-29 12:27:4434 " jump to state " << s; \
35 next_handshake_state_ = s; } while (0)
36#else
37#define GotoState(s) next_handshake_state_ = s
38#endif
39
40const size_t kMaxRecvBufferSize = 4096;
[email protected]fbef13932010-11-23 12:38:5341const int kSessionCacheTimeoutSeconds = 60 * 60;
42const size_t kSessionCacheMaxEntires = 1024;
[email protected]d518cd92010-09-29 12:27:4443
[email protected]109805a2010-12-07 18:17:0644// This method doesn't seemed to have made it into the OpenSSL headers.
45unsigned long SSL_CIPHER_get_id(const SSL_CIPHER* cipher) { return cipher->id; }
46
47// Used for encoding the |connection_status| field of an SSLInfo object.
48int EncodeSSLConnectionStatus(int cipher_suite,
49 int compression,
50 int version) {
51 return ((cipher_suite & SSL_CONNECTION_CIPHERSUITE_MASK) <<
52 SSL_CONNECTION_CIPHERSUITE_SHIFT) |
53 ((compression & SSL_CONNECTION_COMPRESSION_MASK) <<
54 SSL_CONNECTION_COMPRESSION_SHIFT) |
55 ((version & SSL_CONNECTION_VERSION_MASK) <<
56 SSL_CONNECTION_VERSION_SHIFT);
57}
58
59// Returns the net SSL version number (see ssl_connection_status_flags.h) for
60// this SSL connection.
61int GetNetSSLVersion(SSL* ssl) {
[email protected]7e5dd49f2010-12-08 18:33:4962 switch (SSL_version(ssl)) {
[email protected]109805a2010-12-07 18:17:0663 case SSL2_VERSION:
64 return SSL_CONNECTION_VERSION_SSL2;
65 case SSL3_VERSION:
66 return SSL_CONNECTION_VERSION_SSL3;
67 case TLS1_VERSION:
68 return SSL_CONNECTION_VERSION_TLS1;
69 case 0x0302:
70 return SSL_CONNECTION_VERSION_TLS1_1;
71 case 0x0303:
72 return SSL_CONNECTION_VERSION_TLS1_2;
73 default:
74 return SSL_CONNECTION_VERSION_UNKNOWN;
75 }
76}
77
78int MapOpenSSLErrorSSL() {
79 // Walk down the error stack to find the SSLerr generated reason.
80 unsigned long error_code;
81 do {
82 error_code = ERR_get_error();
83 if (error_code == 0)
84 return ERR_SSL_PROTOCOL_ERROR;
85 } while (ERR_GET_LIB(error_code) != ERR_LIB_SSL);
86
87 DVLOG(1) << "OpenSSL SSL error, reason: " << ERR_GET_REASON(error_code)
88 << ", name: " << ERR_error_string(error_code, NULL);
89 switch (ERR_GET_REASON(error_code)) {
90 case SSL_R_READ_TIMEOUT_EXPIRED:
91 return ERR_TIMED_OUT;
92 case SSL_R_BAD_RESPONSE_ARGUMENT:
93 return ERR_INVALID_ARGUMENT;
94 case SSL_R_UNKNOWN_CERTIFICATE_TYPE:
95 case SSL_R_UNKNOWN_CIPHER_TYPE:
96 case SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE:
97 case SSL_R_UNKNOWN_PKEY_TYPE:
98 case SSL_R_UNKNOWN_REMOTE_ERROR_TYPE:
99 case SSL_R_UNKNOWN_SSL_VERSION:
100 return ERR_NOT_IMPLEMENTED;
[email protected]109805a2010-12-07 18:17:06101 case SSL_R_UNSUPPORTED_SSL_VERSION:
102 case SSL_R_NO_CIPHER_MATCH:
103 case SSL_R_NO_SHARED_CIPHER:
104 case SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY:
105 case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION:
106 return ERR_SSL_VERSION_OR_CIPHER_MISMATCH;
107 case SSL_R_SSLV3_ALERT_BAD_CERTIFICATE:
108 case SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE:
109 case SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED:
110 case SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED:
111 case SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN:
112 case SSL_R_TLSV1_ALERT_ACCESS_DENIED:
113 case SSL_R_TLSV1_ALERT_UNKNOWN_CA:
114 return ERR_BAD_SSL_CLIENT_AUTH_CERT;
115 case SSL_R_BAD_DECOMPRESSION:
116 case SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE:
117 return ERR_SSL_DECOMPRESSION_FAILURE_ALERT;
118 case SSL_R_SSLV3_ALERT_BAD_RECORD_MAC:
119 return ERR_SSL_BAD_RECORD_MAC_ALERT;
120 case SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED:
121 return ERR_SSL_UNSAFE_NEGOTIATION;
122 case SSL_R_WRONG_NUMBER_OF_KEY_BITS:
123 return ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY;
[email protected]aa4bb6892010-12-08 10:52:02124 // SSL_R_UNKNOWN_PROTOCOL is reported if premature application data is
125 // received (see http://crbug.com/42538), and also if all the protocol
126 // versions supported by the server were disabled in this socket instance.
127 // Mapped to ERR_SSL_PROTOCOL_ERROR for compatibility with other SSL sockets
128 // in the former scenario.
129 case SSL_R_UNKNOWN_PROTOCOL:
[email protected]109805a2010-12-07 18:17:06130 case SSL_R_SSL_HANDSHAKE_FAILURE:
131 case SSL_R_DECRYPTION_FAILED:
132 case SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC:
133 case SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG:
134 case SSL_R_DIGEST_CHECK_FAILED:
135 case SSL_R_DUPLICATE_COMPRESSION_ID:
136 case SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER:
137 case SSL_R_ENCRYPTED_LENGTH_TOO_LONG:
138 case SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST:
139 case SSL_R_EXCESSIVE_MESSAGE_SIZE:
140 case SSL_R_EXTRA_DATA_IN_MESSAGE:
141 case SSL_R_GOT_A_FIN_BEFORE_A_CCS:
142 case SSL_R_ILLEGAL_PADDING:
143 case SSL_R_INVALID_CHALLENGE_LENGTH:
144 case SSL_R_INVALID_COMMAND:
145 case SSL_R_INVALID_PURPOSE:
146 case SSL_R_INVALID_STATUS_RESPONSE:
147 case SSL_R_INVALID_TICKET_KEYS_LENGTH:
148 case SSL_R_KEY_ARG_TOO_LONG:
149 case SSL_R_READ_WRONG_PACKET_TYPE:
150 case SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE:
151 // TODO(joth): SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE may be returned from the
152 // server after receiving ClientHello if there's no common supported cipher.
153 // Ideally we'd map that specific case to ERR_SSL_VERSION_OR_CIPHER_MISMATCH
154 // to match the NSS implementation. See also http://goo.gl/oMtZW
155 case SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE:
156 case SSL_R_SSLV3_ALERT_NO_CERTIFICATE:
157 case SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER:
158 case SSL_R_TLSV1_ALERT_DECODE_ERROR:
159 case SSL_R_TLSV1_ALERT_DECRYPTION_FAILED:
160 case SSL_R_TLSV1_ALERT_DECRYPT_ERROR:
161 case SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION:
162 case SSL_R_TLSV1_ALERT_INTERNAL_ERROR:
163 case SSL_R_TLSV1_ALERT_NO_RENEGOTIATION:
164 case SSL_R_TLSV1_ALERT_RECORD_OVERFLOW:
165 case SSL_R_TLSV1_ALERT_USER_CANCELLED:
166 return ERR_SSL_PROTOCOL_ERROR;
167 default:
168 LOG(WARNING) << "Unmapped error reason: " << ERR_GET_REASON(error_code);
169 return ERR_FAILED;
170 }
171}
172
173// Converts an OpenSSL error code into a net error code, walking the OpenSSL
174// error stack if needed. Note that |tracer| is not currently used in the
175// implementation, but is passed in anyway as this ensures the caller will clear
176// any residual codes left on the error stack.
[email protected]4b559b4d2011-04-14 17:37:14177int MapOpenSSLError(int err, const crypto::OpenSSLErrStackTracer& tracer) {
[email protected]d518cd92010-09-29 12:27:44178 switch (err) {
179 case SSL_ERROR_WANT_READ:
180 case SSL_ERROR_WANT_WRITE:
181 return ERR_IO_PENDING;
[email protected]170e76c2010-10-04 15:04:20182 case SSL_ERROR_SYSCALL:
[email protected]abc7e06d2010-10-06 15:40:35183 DVLOG(1) << "OpenSSL SYSCALL error, errno " << errno;
[email protected]170e76c2010-10-04 15:04:20184 return ERR_SSL_PROTOCOL_ERROR;
[email protected]109805a2010-12-07 18:17:06185 case SSL_ERROR_SSL:
186 return MapOpenSSLErrorSSL();
[email protected]d518cd92010-09-29 12:27:44187 default:
188 // TODO(joth): Implement full mapping.
189 LOG(WARNING) << "Unknown OpenSSL error " << err;
[email protected]d518cd92010-09-29 12:27:44190 return ERR_SSL_PROTOCOL_ERROR;
191 }
192}
193
[email protected]313834722010-11-17 09:57:18194// We do certificate verification after handshake, so we disable the default
195// by registering a no-op verify function.
196int NoOpVerifyCallback(X509_STORE_CTX*, void *) {
197 DVLOG(3) << "skipping cert verify";
198 return 1;
199}
200
[email protected]fbef13932010-11-23 12:38:53201// OpenSSL manages a cache of SSL_SESSION, this class provides the application
202// side policy for that cache about session re-use: we retain one session per
[email protected]c3456bb2011-12-12 22:22:19203// unique HostPortPair, per shard.
[email protected]fbef13932010-11-23 12:38:53204class SSLSessionCache {
205 public:
206 SSLSessionCache() {}
207
[email protected]c3456bb2011-12-12 22:22:19208 void OnSessionAdded(const HostPortPair& host_and_port,
209 const std::string& shard,
210 SSL_SESSION* session) {
[email protected]fbef13932010-11-23 12:38:53211 // Declare the session cleaner-upper before the lock, so any call into
212 // OpenSSL to free the session will happen after the lock is released.
[email protected]4b559b4d2011-04-14 17:37:14213 crypto::ScopedOpenSSL<SSL_SESSION, SSL_SESSION_free> session_to_free;
[email protected]20305ec2011-01-21 04:55:52214 base::AutoLock lock(lock_);
[email protected]fbef13932010-11-23 12:38:53215
216 DCHECK_EQ(0U, session_map_.count(session));
[email protected]c3456bb2011-12-12 22:22:19217 const std::string cache_key = GetCacheKey(host_and_port, shard);
218
[email protected]fbef13932010-11-23 12:38:53219 std::pair<HostPortMap::iterator, bool> res =
[email protected]c3456bb2011-12-12 22:22:19220 host_port_map_.insert(std::make_pair(cache_key, session));
[email protected]fbef13932010-11-23 12:38:53221 if (!res.second) { // Already exists: replace old entry.
222 session_to_free.reset(res.first->second);
223 session_map_.erase(session_to_free.get());
224 res.first->second = session;
225 }
226 DVLOG(2) << "Adding session " << session << " => "
[email protected]c3456bb2011-12-12 22:22:19227 << cache_key << ", new entry = " << res.second;
228 DCHECK(host_port_map_[cache_key] == session);
[email protected]fbef13932010-11-23 12:38:53229 session_map_[session] = res.first;
230 DCHECK_EQ(host_port_map_.size(), session_map_.size());
231 DCHECK_LE(host_port_map_.size(), kSessionCacheMaxEntires);
[email protected]313834722010-11-17 09:57:18232 }
[email protected]fbef13932010-11-23 12:38:53233
234 void OnSessionRemoved(SSL_SESSION* session) {
235 // Declare the session cleaner-upper before the lock, so any call into
236 // OpenSSL to free the session will happen after the lock is released.
[email protected]4b559b4d2011-04-14 17:37:14237 crypto::ScopedOpenSSL<SSL_SESSION, SSL_SESSION_free> session_to_free;
[email protected]20305ec2011-01-21 04:55:52238 base::AutoLock lock(lock_);
[email protected]fbef13932010-11-23 12:38:53239
240 SessionMap::iterator it = session_map_.find(session);
241 if (it == session_map_.end())
242 return;
[email protected]c3456bb2011-12-12 22:22:19243 DVLOG(2) << "Remove session " << session << " => " << it->second->first;
[email protected]fbef13932010-11-23 12:38:53244 DCHECK(it->second->second == session);
245 host_port_map_.erase(it->second);
246 session_map_.erase(it);
247 session_to_free.reset(session);
248 DCHECK_EQ(host_port_map_.size(), session_map_.size());
[email protected]313834722010-11-17 09:57:18249 }
[email protected]fbef13932010-11-23 12:38:53250
251 // Looks up the host:port in the cache, and if a session is found it is added
252 // to |ssl|, returning true on success.
[email protected]c3456bb2011-12-12 22:22:19253 bool SetSSLSession(SSL* ssl, const HostPortPair& host_and_port,
254 const std::string& shard) {
[email protected]20305ec2011-01-21 04:55:52255 base::AutoLock lock(lock_);
[email protected]c3456bb2011-12-12 22:22:19256 const std::string cache_key = GetCacheKey(host_and_port, shard);
257 HostPortMap::iterator it = host_port_map_.find(cache_key);
[email protected]fbef13932010-11-23 12:38:53258 if (it == host_port_map_.end())
259 return false;
[email protected]c3456bb2011-12-12 22:22:19260 DVLOG(2) << "Lookup session: " << it->second << " => " << cache_key;
[email protected]fbef13932010-11-23 12:38:53261 SSL_SESSION* session = it->second;
262 DCHECK(session);
263 DCHECK(session_map_[session] == it);
264 // Ideally we'd release |lock_| before calling into OpenSSL here, however
265 // that opens a small risk |session| will go out of scope before it is used.
266 // Alternatively we would take a temporary local refcount on |session|,
267 // except OpenSSL does not provide a public API for adding a ref (c.f.
268 // SSL_SESSION_free which decrements the ref).
269 return SSL_set_session(ssl, session) == 1;
270 }
271
[email protected]c3456bb2011-12-12 22:22:19272 // Flush removes all entries from the cache. This is called when a client
273 // certificate is added.
274 void Flush() {
275 for (HostPortMap::iterator i = host_port_map_.begin();
276 i != host_port_map_.end(); i++) {
277 SSL_SESSION_free(i->second);
278 }
279 host_port_map_.clear();
280 session_map_.clear();
281 }
282
[email protected]fbef13932010-11-23 12:38:53283 private:
[email protected]c3456bb2011-12-12 22:22:19284 static std::string GetCacheKey(const HostPortPair& host_and_port,
285 const std::string& shard) {
286 return host_and_port.ToString() + "/" + shard;
287 }
288
[email protected]fbef13932010-11-23 12:38:53289 // A pair of maps to allow bi-directional lookups between host:port and an
[email protected]109805a2010-12-07 18:17:06290 // associated session.
[email protected]c3456bb2011-12-12 22:22:19291 typedef std::map<std::string, SSL_SESSION*> HostPortMap;
[email protected]fbef13932010-11-23 12:38:53292 typedef std::map<SSL_SESSION*, HostPortMap::iterator> SessionMap;
293 HostPortMap host_port_map_;
294 SessionMap session_map_;
295
296 // Protects access to both the above maps.
[email protected]20305ec2011-01-21 04:55:52297 base::Lock lock_;
[email protected]fbef13932010-11-23 12:38:53298
299 DISALLOW_COPY_AND_ASSIGN(SSLSessionCache);
[email protected]313834722010-11-17 09:57:18300};
301
[email protected]fbef13932010-11-23 12:38:53302class SSLContext {
303 public:
[email protected]b29af7d2010-12-14 11:52:47304 static SSLContext* GetInstance() { return Singleton<SSLContext>::get(); }
[email protected]fbef13932010-11-23 12:38:53305 SSL_CTX* ssl_ctx() { return ssl_ctx_.get(); }
306 SSLSessionCache* session_cache() { return &session_cache_; }
307
308 SSLClientSocketOpenSSL* GetClientSocketFromSSL(SSL* ssl) {
309 DCHECK(ssl);
310 SSLClientSocketOpenSSL* socket = static_cast<SSLClientSocketOpenSSL*>(
311 SSL_get_ex_data(ssl, ssl_socket_data_index_));
312 DCHECK(socket);
313 return socket;
314 }
315
316 bool SetClientSocketForSSL(SSL* ssl, SSLClientSocketOpenSSL* socket) {
317 return SSL_set_ex_data(ssl, ssl_socket_data_index_, socket) != 0;
318 }
319
320 private:
321 friend struct DefaultSingletonTraits<SSLContext>;
322
323 SSLContext() {
[email protected]4b559b4d2011-04-14 17:37:14324 crypto::EnsureOpenSSLInit();
[email protected]fbef13932010-11-23 12:38:53325 ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0);
326 DCHECK_NE(ssl_socket_data_index_, -1);
327 ssl_ctx_.reset(SSL_CTX_new(SSLv23_client_method()));
328 SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), NoOpVerifyCallback, NULL);
329 SSL_CTX_set_session_cache_mode(ssl_ctx_.get(), SSL_SESS_CACHE_CLIENT);
330 SSL_CTX_sess_set_new_cb(ssl_ctx_.get(), NewSessionCallbackStatic);
331 SSL_CTX_sess_set_remove_cb(ssl_ctx_.get(), RemoveSessionCallbackStatic);
332 SSL_CTX_set_timeout(ssl_ctx_.get(), kSessionCacheTimeoutSeconds);
333 SSL_CTX_sess_set_cache_size(ssl_ctx_.get(), kSessionCacheMaxEntires);
[email protected]718c9672010-12-02 10:04:10334 SSL_CTX_set_client_cert_cb(ssl_ctx_.get(), ClientCertCallback);
[email protected]ea4a1c6a2010-12-09 13:33:28335#if defined(OPENSSL_NPN_NEGOTIATED)
336 // TODO(kristianm): Only select this if ssl_config_.next_proto is not empty.
337 // It would be better if the callback were not a global setting,
338 // but that is an OpenSSL issue.
339 SSL_CTX_set_next_proto_select_cb(ssl_ctx_.get(), SelectNextProtoCallback,
340 NULL);
341#endif
[email protected]fbef13932010-11-23 12:38:53342 }
343
344 static int NewSessionCallbackStatic(SSL* ssl, SSL_SESSION* session) {
[email protected]b29af7d2010-12-14 11:52:47345 return GetInstance()->NewSessionCallback(ssl, session);
[email protected]fbef13932010-11-23 12:38:53346 }
347
348 int NewSessionCallback(SSL* ssl, SSL_SESSION* session) {
349 SSLClientSocketOpenSSL* socket = GetClientSocketFromSSL(ssl);
[email protected]c3456bb2011-12-12 22:22:19350 session_cache_.OnSessionAdded(socket->host_and_port(),
351 socket->ssl_session_cache_shard(),
352 session);
[email protected]fbef13932010-11-23 12:38:53353 return 1; // 1 => We took ownership of |session|.
354 }
355
356 static void RemoveSessionCallbackStatic(SSL_CTX* ctx, SSL_SESSION* session) {
[email protected]b29af7d2010-12-14 11:52:47357 return GetInstance()->RemoveSessionCallback(ctx, session);
[email protected]fbef13932010-11-23 12:38:53358 }
359
360 void RemoveSessionCallback(SSL_CTX* ctx, SSL_SESSION* session) {
361 DCHECK(ctx == ssl_ctx());
362 session_cache_.OnSessionRemoved(session);
363 }
364
[email protected]718c9672010-12-02 10:04:10365 static int ClientCertCallback(SSL* ssl, X509** x509, EVP_PKEY** pkey) {
[email protected]b29af7d2010-12-14 11:52:47366 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl);
[email protected]718c9672010-12-02 10:04:10367 CHECK(socket);
368 return socket->ClientCertRequestCallback(ssl, x509, pkey);
369 }
370
[email protected]ea4a1c6a2010-12-09 13:33:28371 static int SelectNextProtoCallback(SSL* ssl,
372 unsigned char** out, unsigned char* outlen,
373 const unsigned char* in,
374 unsigned int inlen, void* arg) {
[email protected]b29af7d2010-12-14 11:52:47375 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl);
[email protected]ea4a1c6a2010-12-09 13:33:28376 return socket->SelectNextProtoCallback(out, outlen, in, inlen);
377 }
378
[email protected]fbef13932010-11-23 12:38:53379 // This is the index used with SSL_get_ex_data to retrieve the owner
380 // SSLClientSocketOpenSSL object from an SSL instance.
381 int ssl_socket_data_index_;
382
[email protected]c3456bb2011-12-12 22:22:19383 // session_cache_ must appear before |ssl_ctx_| because the destruction of
384 // |ssl_ctx_| may trigger callbacks into |session_cache_|. Therefore,
385 // |session_cache_| must be destructed after |ssl_ctx_|.
[email protected]fbef13932010-11-23 12:38:53386 SSLSessionCache session_cache_;
[email protected]c3456bb2011-12-12 22:22:19387 crypto::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_;
[email protected]fbef13932010-11-23 12:38:53388};
[email protected]313834722010-11-17 09:57:18389
[email protected]fb10e2282010-12-01 17:08:48390// Utility to construct the appropriate set & clear masks for use the OpenSSL
391// options and mode configuration functions. (SSL_set_options etc)
392struct SslSetClearMask {
393 SslSetClearMask() : set_mask(0), clear_mask(0) {}
394 void ConfigureFlag(long flag, bool state) {
395 (state ? set_mask : clear_mask) |= flag;
396 // Make sure we haven't got any intersection in the set & clear options.
397 DCHECK_EQ(0, set_mask & clear_mask) << flag << ":" << state;
398 }
399 long set_mask;
400 long clear_mask;
401};
402
[email protected]3b112772010-10-04 10:54:49403} // namespace
[email protected]d518cd92010-09-29 12:27:44404
[email protected]c3456bb2011-12-12 22:22:19405// static
406void SSLClientSocket::ClearSessionCache() {
407 SSLContext* context = SSLContext::GetInstance();
408 context->session_cache()->Flush();
409}
410
[email protected]d518cd92010-09-29 12:27:44411SSLClientSocketOpenSSL::SSLClientSocketOpenSSL(
412 ClientSocketHandle* transport_socket,
[email protected]055d7f22010-11-15 12:03:12413 const HostPortPair& host_and_port,
[email protected]822581d2010-12-16 17:27:15414 const SSLConfig& ssl_config,
[email protected]feb79bcd2011-07-21 16:55:17415 const SSLClientSocketContext& context)
[email protected]83039bb2011-12-09 18:43:55416 : transport_send_busy_(false),
[email protected]d518cd92010-09-29 12:27:44417 transport_recv_busy_(false),
[email protected]fbef13932010-11-23 12:38:53418 completed_handshake_(false),
[email protected]d518cd92010-09-29 12:27:44419 client_auth_cert_needed_(false),
[email protected]feb79bcd2011-07-21 16:55:17420 cert_verifier_(context.cert_verifier),
[email protected]d518cd92010-09-29 12:27:44421 ssl_(NULL),
422 transport_bio_(NULL),
423 transport_(transport_socket),
[email protected]055d7f22010-11-15 12:03:12424 host_and_port_(host_and_port),
[email protected]d518cd92010-09-29 12:27:44425 ssl_config_(ssl_config),
[email protected]c3456bb2011-12-12 22:22:19426 ssl_session_cache_shard_(context.ssl_session_cache_shard),
[email protected]fbef13932010-11-23 12:38:53427 trying_cached_session_(false),
[email protected]013c17c2012-01-21 19:09:01428 next_handshake_state_(STATE_NONE),
[email protected]ea4a1c6a2010-12-09 13:33:28429 npn_status_(kNextProtoUnsupported),
[email protected]d518cd92010-09-29 12:27:44430 net_log_(transport_socket->socket()->NetLog()) {
431}
432
433SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() {
434 Disconnect();
435}
436
[email protected]d518cd92010-09-29 12:27:44437bool SSLClientSocketOpenSSL::Init() {
[email protected]9e733f32010-10-04 18:19:08438 DCHECK(!ssl_);
439 DCHECK(!transport_bio_);
440
[email protected]b29af7d2010-12-14 11:52:47441 SSLContext* context = SSLContext::GetInstance();
[email protected]4b559b4d2011-04-14 17:37:14442 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
[email protected]d518cd92010-09-29 12:27:44443
[email protected]fbef13932010-11-23 12:38:53444 ssl_ = SSL_new(context->ssl_ctx());
445 if (!ssl_ || !context->SetClientSocketForSSL(ssl_, this))
[email protected]d518cd92010-09-29 12:27:44446 return false;
[email protected]fbef13932010-11-23 12:38:53447
448 if (!SSL_set_tlsext_host_name(ssl_, host_and_port_.host().c_str()))
449 return false;
450
451 trying_cached_session_ =
[email protected]c3456bb2011-12-12 22:22:19452 context->session_cache()->SetSSLSession(ssl_, host_and_port_,
453 ssl_session_cache_shard_);
[email protected]d518cd92010-09-29 12:27:44454
455 BIO* ssl_bio = NULL;
[email protected]fbef13932010-11-23 12:38:53456 // 0 => use default buffer sizes.
457 if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0))
[email protected]d518cd92010-09-29 12:27:44458 return false;
[email protected]d518cd92010-09-29 12:27:44459 DCHECK(ssl_bio);
460 DCHECK(transport_bio_);
461
462 SSL_set_bio(ssl_, ssl_bio, ssl_bio);
463
[email protected]9e733f32010-10-04 18:19:08464 // OpenSSL defaults some options to on, others to off. To avoid ambiguity,
465 // set everything we care about to an absolute value.
[email protected]fb10e2282010-12-01 17:08:48466 SslSetClearMask options;
467 options.ConfigureFlag(SSL_OP_NO_SSLv2, true);
468 options.ConfigureFlag(SSL_OP_NO_SSLv3, !ssl_config_.ssl3_enabled);
469 options.ConfigureFlag(SSL_OP_NO_TLSv1, !ssl_config_.tls1_enabled);
470
471#if defined(SSL_OP_NO_COMPRESSION)
472 // If TLS was disabled also disable compression, to provide maximum site
473 // compatibility in the case of protocol fallback. See http://crbug.com/31628
474 options.ConfigureFlag(SSL_OP_NO_COMPRESSION, !ssl_config_.tls1_enabled);
475#endif
[email protected]9e733f32010-10-04 18:19:08476
477 // TODO(joth): Set this conditionally, see http://crbug.com/55410
[email protected]fb10e2282010-12-01 17:08:48478 options.ConfigureFlag(SSL_OP_LEGACY_SERVER_CONNECT, true);
[email protected]9e733f32010-10-04 18:19:08479
[email protected]fb10e2282010-12-01 17:08:48480 SSL_set_options(ssl_, options.set_mask);
481 SSL_clear_options(ssl_, options.clear_mask);
[email protected]9e733f32010-10-04 18:19:08482
[email protected]fb10e2282010-12-01 17:08:48483 // Same as above, this time for the SSL mode.
484 SslSetClearMask mode;
[email protected]9e733f32010-10-04 18:19:08485
[email protected]fb10e2282010-12-01 17:08:48486#if defined(SSL_MODE_HANDSHAKE_CUTTHROUGH)
487 mode.ConfigureFlag(SSL_MODE_HANDSHAKE_CUTTHROUGH,
488 ssl_config_.false_start_enabled &&
489 !SSLConfigService::IsKnownFalseStartIncompatibleServer(
490 host_and_port_.host()));
491#endif
492
493#if defined(SSL_MODE_RELEASE_BUFFERS)
494 mode.ConfigureFlag(SSL_MODE_RELEASE_BUFFERS, true);
495#endif
496
497#if defined(SSL_MODE_SMALL_BUFFERS)
498 mode.ConfigureFlag(SSL_MODE_SMALL_BUFFERS, true);
499#endif
500
501 SSL_set_mode(ssl_, mode.set_mask);
502 SSL_clear_mode(ssl_, mode.clear_mask);
[email protected]109805a2010-12-07 18:17:06503
504 // Removing ciphers by ID from OpenSSL is a bit involved as we must use the
505 // textual name with SSL_set_cipher_list because there is no public API to
506 // directly remove a cipher by ID.
507 STACK_OF(SSL_CIPHER)* ciphers = SSL_get_ciphers(ssl_);
508 DCHECK(ciphers);
509 // See SSLConfig::disabled_cipher_suites for description of the suites
510 // disabled by default.
511 std::string command("DEFAULT:!NULL:!aNULL:!IDEA:!FZA");
512 // Walk through all the installed ciphers, seeing if any need to be
513 // appended to the cipher removal |command|.
514 for (int i = 0; i < sk_SSL_CIPHER_num(ciphers); ++i) {
515 const SSL_CIPHER* cipher = sk_SSL_CIPHER_value(ciphers, i);
516 const uint16 id = SSL_CIPHER_get_id(cipher);
517 // Remove any ciphers with a strength of less than 80 bits. Note the NSS
518 // implementation uses "effective" bits here but OpenSSL does not provide
519 // this detail. This only impacts Triple DES: reports 112 vs. 168 bits,
520 // both of which are greater than 80 anyway.
521 bool disable = SSL_CIPHER_get_bits(cipher, NULL) < 80;
522 if (!disable) {
523 disable = std::find(ssl_config_.disabled_cipher_suites.begin(),
524 ssl_config_.disabled_cipher_suites.end(), id) !=
525 ssl_config_.disabled_cipher_suites.end();
526 }
527 if (disable) {
528 const char* name = SSL_CIPHER_get_name(cipher);
529 DVLOG(3) << "Found cipher to remove: '" << name << "', ID: " << id
530 << " strength: " << SSL_CIPHER_get_bits(cipher, NULL);
531 command.append(":!");
532 command.append(name);
533 }
534 }
535 int rv = SSL_set_cipher_list(ssl_, command.c_str());
536 // If this fails (rv = 0) it means there are no ciphers enabled on this SSL.
537 // This will almost certainly result in the socket failing to complete the
538 // handshake at which point the appropriate error is bubbled up to the client.
539 LOG_IF(WARNING, rv != 1) << "SSL_set_cipher_list('" << command << "') "
540 "returned " << rv;
[email protected]d518cd92010-09-29 12:27:44541 return true;
542}
543
[email protected]5ac981e182010-12-06 17:56:27544int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl,
545 X509** x509,
546 EVP_PKEY** pkey) {
547 DVLOG(3) << "OpenSSL ClientCertRequestCallback called";
548 DCHECK(ssl == ssl_);
549 DCHECK(*x509 == NULL);
550 DCHECK(*pkey == NULL);
551
552 if (!ssl_config_.send_client_cert) {
553 client_auth_cert_needed_ = true;
554 return -1; // Suspends handshake.
555 }
556
557 // Second pass: a client certificate should have been selected.
558 if (ssl_config_.client_cert) {
[email protected]0c6523f2010-12-10 10:56:24559 EVP_PKEY* privkey = OpenSSLPrivateKeyStore::GetInstance()->FetchPrivateKey(
560 X509_PUBKEY_get(X509_get_X509_PUBKEY(
561 ssl_config_.client_cert->os_cert_handle())));
562 if (privkey) {
563 // TODO(joth): (copied from NSS) We should wait for server certificate
564 // verification before sending our credentials. See http://crbug.com/13934
565 *x509 = X509Certificate::DupOSCertHandle(
566 ssl_config_.client_cert->os_cert_handle());
567 *pkey = privkey;
568 return 1;
569 }
570 LOG(WARNING) << "Client cert found without private key";
[email protected]5ac981e182010-12-06 17:56:27571 }
572
573 // Send no client certificate.
574 return 0;
575}
576
[email protected]d518cd92010-09-29 12:27:44577// SSLClientSocket methods
578
579void SSLClientSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) {
[email protected]170e76c2010-10-04 15:04:20580 ssl_info->Reset();
581 if (!server_cert_)
582 return;
583
[email protected]170e76c2010-10-04 15:04:20584 ssl_info->cert = server_cert_;
585 ssl_info->cert_status = server_cert_verify_result_.cert_status;
[email protected]1f522492011-04-13 22:06:38586 ssl_info->is_issued_by_known_root =
587 server_cert_verify_result_.is_issued_by_known_root;
588 ssl_info->public_key_hashes =
589 server_cert_verify_result_.public_key_hashes;
[email protected]17a60a52011-10-28 01:18:10590 ssl_info->client_cert_sent =
591 ssl_config_.send_client_cert && ssl_config_.client_cert;
[email protected]2907525c2010-10-08 15:53:52592
593 const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl_);
594 CHECK(cipher);
595 ssl_info->security_bits = SSL_CIPHER_get_bits(cipher, NULL);
[email protected]2907525c2010-10-08 15:53:52596 const COMP_METHOD* compression = SSL_get_current_compression(ssl_);
[email protected]109805a2010-12-07 18:17:06597
598 ssl_info->connection_status = EncodeSSLConnectionStatus(
599 SSL_CIPHER_get_id(cipher),
600 compression ? compression->type : 0,
601 GetNetSSLVersion(ssl_));
[email protected]9e733f32010-10-04 18:19:08602
603 bool peer_supports_renego_ext = !!SSL_get_secure_renegotiation_support(ssl_);
604 if (!peer_supports_renego_ext)
605 ssl_info->connection_status |= SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION;
[email protected]109805a2010-12-07 18:17:06606 UMA_HISTOGRAM_ENUMERATION("Net.RenegotiationExtensionSupported",
607 implicit_cast<int>(peer_supports_renego_ext), 2);
[email protected]9e733f32010-10-04 18:19:08608
609 if (ssl_config_.ssl3_fallback)
610 ssl_info->connection_status |= SSL_CONNECTION_SSL3_FALLBACK;
[email protected]109805a2010-12-07 18:17:06611
612 DVLOG(3) << "Encoded connection status: cipher suite = "
613 << SSLConnectionStatusToCipherSuite(ssl_info->connection_status)
614 << " compression = "
615 << SSLConnectionStatusToCompression(ssl_info->connection_status)
616 << " version = "
617 << SSLConnectionStatusToVersion(ssl_info->connection_status);
[email protected]d518cd92010-09-29 12:27:44618}
619
620void SSLClientSocketOpenSSL::GetSSLCertRequestInfo(
621 SSLCertRequestInfo* cert_request_info) {
[email protected]718c9672010-12-02 10:04:10622 cert_request_info->host_and_port = host_and_port_.ToString();
623 cert_request_info->client_certs = client_certs_;
[email protected]d518cd92010-09-29 12:27:44624}
625
[email protected]b0ff3f82011-07-23 05:12:39626int SSLClientSocketOpenSSL::ExportKeyingMaterial(
627 const base::StringPiece& label, const base::StringPiece& context,
628 unsigned char *out, unsigned int outlen) {
629 return ERR_NOT_IMPLEMENTED;
630}
631
[email protected]d518cd92010-09-29 12:27:44632SSLClientSocket::NextProtoStatus SSLClientSocketOpenSSL::GetNextProto(
[email protected]55e973d2011-12-05 23:03:24633 std::string* proto, std::string* server_protos) {
[email protected]ea4a1c6a2010-12-09 13:33:28634 *proto = npn_proto_;
[email protected]55e973d2011-12-05 23:03:24635 *server_protos = server_protos_;
[email protected]ea4a1c6a2010-12-09 13:33:28636 return npn_status_;
[email protected]d518cd92010-09-29 12:27:44637}
638
639void SSLClientSocketOpenSSL::DoReadCallback(int rv) {
640 // Since Run may result in Read being called, clear |user_read_callback_|
641 // up front.
[email protected]83039bb2011-12-09 18:43:55642 CompletionCallback c = user_read_callback_;
643 user_read_callback_.Reset();
644 user_read_buf_ = NULL;
645 user_read_buf_len_ = 0;
646 c.Run(rv);
[email protected]d518cd92010-09-29 12:27:44647}
648
649void SSLClientSocketOpenSSL::DoWriteCallback(int rv) {
650 // Since Run may result in Write being called, clear |user_write_callback_|
651 // up front.
[email protected]83039bb2011-12-09 18:43:55652 CompletionCallback c = user_write_callback_;
653 user_write_callback_.Reset();
[email protected]f749f9c2011-12-09 01:06:19654 user_write_buf_ = NULL;
655 user_write_buf_len_ = 0;
[email protected]83039bb2011-12-09 18:43:55656 c.Run(rv);
[email protected]d518cd92010-09-29 12:27:44657}
658
[email protected]83039bb2011-12-09 18:43:55659// StreamSocket implementation.
[email protected]dbf036f2011-12-06 23:33:24660int SSLClientSocketOpenSSL::Connect(const CompletionCallback& callback) {
661 net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT, NULL);
662
663 // Set up new ssl object.
664 if (!Init()) {
665 int result = ERR_UNEXPECTED;
666 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, result);
667 return result;
668 }
669
670 // Set SSL to client mode. Handshake happens in the loop below.
671 SSL_set_connect_state(ssl_);
672
673 GotoState(STATE_HANDSHAKE);
674 int rv = DoHandshakeLoop(net::OK);
675 if (rv == ERR_IO_PENDING) {
[email protected]d518cd92010-09-29 12:27:44676 user_connect_callback_ = callback;
677 } else {
[email protected]d7fd1782011-02-08 19:16:43678 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
[email protected]d518cd92010-09-29 12:27:44679 }
680
681 return rv > OK ? OK : rv;
682}
683
684void SSLClientSocketOpenSSL::Disconnect() {
[email protected]170e76c2010-10-04 15:04:20685 if (ssl_) {
[email protected]c3456bb2011-12-12 22:22:19686 // Calling SSL_shutdown prevents the session from being marked as
687 // unresumable.
688 SSL_shutdown(ssl_);
[email protected]170e76c2010-10-04 15:04:20689 SSL_free(ssl_);
690 ssl_ = NULL;
691 }
692 if (transport_bio_) {
693 BIO_free_all(transport_bio_);
694 transport_bio_ = NULL;
695 }
696
[email protected]0f7804ec2011-10-07 20:04:18697 // Shut down anything that may call us back.
[email protected]170e76c2010-10-04 15:04:20698 verifier_.reset();
699 transport_->socket()->Disconnect();
700
[email protected]d518cd92010-09-29 12:27:44701 // Null all callbacks, delete all buffers.
702 transport_send_busy_ = false;
703 send_buffer_ = NULL;
704 transport_recv_busy_ = false;
705 recv_buffer_ = NULL;
706
[email protected]dbf036f2011-12-06 23:33:24707 user_connect_callback_.Reset();
[email protected]3f55aa12011-12-07 02:03:33708 user_read_callback_.Reset();
[email protected]83039bb2011-12-09 18:43:55709 user_write_callback_.Reset();
[email protected]d518cd92010-09-29 12:27:44710 user_read_buf_ = NULL;
711 user_read_buf_len_ = 0;
712 user_write_buf_ = NULL;
713 user_write_buf_len_ = 0;
714
[email protected]170e76c2010-10-04 15:04:20715 server_cert_verify_result_.Reset();
[email protected]d518cd92010-09-29 12:27:44716 completed_handshake_ = false;
[email protected]fbef13932010-11-23 12:38:53717
718 client_certs_.clear();
719 client_auth_cert_needed_ = false;
[email protected]d518cd92010-09-29 12:27:44720}
721
722int SSLClientSocketOpenSSL::DoHandshakeLoop(int last_io_result) {
[email protected]d518cd92010-09-29 12:27:44723 int rv = last_io_result;
724 do {
725 // Default to STATE_NONE for next state.
726 // (This is a quirk carried over from the windows
727 // implementation. It makes reading the logs a bit harder.)
728 // State handlers can and often do call GotoState just
729 // to stay in the current state.
730 State state = next_handshake_state_;
731 GotoState(STATE_NONE);
732 switch (state) {
[email protected]d518cd92010-09-29 12:27:44733 case STATE_HANDSHAKE:
734 rv = DoHandshake();
735 break;
[email protected]d518cd92010-09-29 12:27:44736 case STATE_VERIFY_CERT:
737 DCHECK(rv == OK);
738 rv = DoVerifyCert(rv);
739 break;
740 case STATE_VERIFY_CERT_COMPLETE:
741 rv = DoVerifyCertComplete(rv);
742 break;
[email protected]013c17c2012-01-21 19:09:01743 case STATE_NONE:
[email protected]d518cd92010-09-29 12:27:44744 default:
745 rv = ERR_UNEXPECTED;
746 NOTREACHED() << "unexpected state" << state;
747 break;
748 }
749
[email protected]013c17c2012-01-21 19:09:01750 bool network_moved = DoTransportIO();
751 if (network_moved && next_handshake_state_ == STATE_HANDSHAKE) {
752 // In general we exit the loop if rv is ERR_IO_PENDING. In this
753 // special case we keep looping even if rv is ERR_IO_PENDING because
754 // the transport IO may allow DoHandshake to make progress.
755 rv = OK; // This causes us to stay in the loop.
756 }
757 } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
[email protected]d518cd92010-09-29 12:27:44758 return rv;
759}
760
761int SSLClientSocketOpenSSL::DoHandshake() {
[email protected]4b559b4d2011-04-14 17:37:14762 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
[email protected]d518cd92010-09-29 12:27:44763 int net_error = net::OK;
764 int rv = SSL_do_handshake(ssl_);
765
[email protected]718c9672010-12-02 10:04:10766 if (client_auth_cert_needed_) {
767 net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
768 // If the handshake already succeeded (because the server requests but
769 // doesn't require a client cert), we need to invalidate the SSL session
770 // so that we won't try to resume the non-client-authenticated session in
771 // the next handshake. This will cause the server to ask for a client
772 // cert again.
773 if (rv == 1) {
774 // Remove from session cache but don't clear this connection.
775 SSL_SESSION* session = SSL_get_session(ssl_);
776 if (session) {
777 int rv = SSL_CTX_remove_session(SSL_get_SSL_CTX(ssl_), session);
778 LOG_IF(WARNING, !rv) << "Couldn't invalidate SSL session: " << session;
779 }
780 }
781 } else if (rv == 1) {
[email protected]fbef13932010-11-23 12:38:53782 if (trying_cached_session_ && logging::DEBUG_MODE) {
783 DVLOG(2) << "Result of session reuse for " << host_and_port_.ToString()
784 << " is: " << (SSL_session_reused(ssl_) ? "Success" : "Fail");
785 }
[email protected]d518cd92010-09-29 12:27:44786 // SSL handshake is completed. Let's verify the certificate.
[email protected]abc7e06d2010-10-06 15:40:35787 const bool got_cert = !!UpdateServerCert();
788 DCHECK(got_cert);
[email protected]59468382011-11-04 02:22:04789 if (net_log_.IsLoggingBytes()) {
790 net_log_.AddEvent(
791 NetLog::TYPE_SSL_CERTIFICATES_RECEIVED,
792 make_scoped_refptr(new X509CertificateNetLogParam(server_cert_)));
793 }
[email protected]abc7e06d2010-10-06 15:40:35794 GotoState(STATE_VERIFY_CERT);
[email protected]d518cd92010-09-29 12:27:44795 } else {
796 int ssl_error = SSL_get_error(ssl_, rv);
[email protected]109805a2010-12-07 18:17:06797 net_error = MapOpenSSLError(ssl_error, err_tracer);
[email protected]d518cd92010-09-29 12:27:44798
799 // If not done, stay in this state
[email protected]170e76c2010-10-04 15:04:20800 if (net_error == ERR_IO_PENDING) {
801 GotoState(STATE_HANDSHAKE);
802 } else {
803 LOG(ERROR) << "handshake failed; returned " << rv
804 << ", SSL error code " << ssl_error
805 << ", net_error " << net_error;
[email protected]109805a2010-12-07 18:17:06806 net_log_.AddEvent(
807 NetLog::TYPE_SSL_HANDSHAKE_ERROR,
808 make_scoped_refptr(new SSLErrorParams(net_error, ssl_error)));
[email protected]170e76c2010-10-04 15:04:20809 }
810 }
811 return net_error;
812}
813
[email protected]ae7c9f42011-11-21 11:41:16814// SelectNextProtoCallback is called by OpenSSL during the handshake. If the
815// server supports NPN, selects a protocol from the list that the server
816// provides. According to third_party/openssl/openssl/ssl/ssl_lib.c, the
817// callback can assume that |in| is syntactically valid.
[email protected]ea4a1c6a2010-12-09 13:33:28818int SSLClientSocketOpenSSL::SelectNextProtoCallback(unsigned char** out,
819 unsigned char* outlen,
820 const unsigned char* in,
821 unsigned int inlen) {
822#if defined(OPENSSL_NPN_NEGOTIATED)
823 if (ssl_config_.next_protos.empty()) {
[email protected]32e1dee2010-12-09 18:36:24824 *out = reinterpret_cast<uint8*>(const_cast<char*>("http/1.1"));
[email protected]ea4a1c6a2010-12-09 13:33:28825 *outlen = 8;
826 npn_status_ = SSLClientSocket::kNextProtoUnsupported;
827 return SSL_TLSEXT_ERR_OK;
828 }
829
[email protected]ae7c9f42011-11-21 11:41:16830 // Assume there's no overlap between our protocols and the server's list.
831 int status = OPENSSL_NPN_NO_OVERLAP;
832 *out = const_cast<unsigned char*>(in) + 1;
833 *outlen = in[0];
834
835 // For each protocol in server preference order, see if we support it.
836 for (unsigned int i = 0; i < inlen; i += in[i] + 1) {
837 for (std::vector<std::string>::const_iterator
838 j = ssl_config_.next_protos.begin();
839 j != ssl_config_.next_protos.end(); ++j) {
840 if (in[i] == j->size() &&
841 memcmp(&in[i + 1], j->data(), in[i]) == 0) {
842 // We find a match.
843 *out = const_cast<unsigned char*>(in) + i + 1;
844 *outlen = in[i];
845 status = OPENSSL_NPN_NEGOTIATED;
846 break;
847 }
848 }
849 if (status == OPENSSL_NPN_NEGOTIATED)
850 break;
851 }
[email protected]ea4a1c6a2010-12-09 13:33:28852
853 npn_proto_.assign(reinterpret_cast<const char*>(*out), *outlen);
[email protected]55e973d2011-12-05 23:03:24854 server_protos_.assign(reinterpret_cast<const char*>(in), inlen);
[email protected]ea4a1c6a2010-12-09 13:33:28855 switch (status) {
[email protected]ea4a1c6a2010-12-09 13:33:28856 case OPENSSL_NPN_NEGOTIATED:
857 npn_status_ = SSLClientSocket::kNextProtoNegotiated;
858 break;
859 case OPENSSL_NPN_NO_OVERLAP:
860 npn_status_ = SSLClientSocket::kNextProtoNoOverlap;
861 break;
862 default:
863 NOTREACHED() << status;
864 break;
865 }
[email protected]32e1dee2010-12-09 18:36:24866 DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_;
[email protected]ea4a1c6a2010-12-09 13:33:28867#endif
868 return SSL_TLSEXT_ERR_OK;
869}
870
[email protected]170e76c2010-10-04 15:04:20871int SSLClientSocketOpenSSL::DoVerifyCert(int result) {
872 DCHECK(server_cert_);
873 GotoState(STATE_VERIFY_CERT_COMPLETE);
[email protected]170e76c2010-10-04 15:04:20874
[email protected]70d66502011-09-23 00:55:08875 CertStatus cert_status;
[email protected]4dc832e2011-04-28 22:04:24876 if (ssl_config_.IsAllowedBadCert(server_cert_, &cert_status)) {
877 VLOG(1) << "Received an expected bad cert with status: " << cert_status;
878 server_cert_verify_result_.Reset();
879 server_cert_verify_result_.cert_status = cert_status;
[email protected]eb8414e2011-07-30 08:47:47880 server_cert_verify_result_.verified_cert = server_cert_;
[email protected]4dc832e2011-04-28 22:04:24881 return OK;
882 }
883
884 int flags = 0;
[email protected]170e76c2010-10-04 15:04:20885 if (ssl_config_.rev_checking_enabled)
886 flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED;
887 if (ssl_config_.verify_ev_cert)
888 flags |= X509Certificate::VERIFY_EV_CERT;
[email protected]822581d2010-12-16 17:27:15889 verifier_.reset(new SingleRequestCertVerifier(cert_verifier_));
[email protected]0f7804ec2011-10-07 20:04:18890 return verifier_->Verify(
891 server_cert_, host_and_port_.host(), flags,
[email protected]a642e33d2011-10-25 19:50:49892 NULL /* no CRL set */,
[email protected]0f7804ec2011-10-07 20:04:18893 &server_cert_verify_result_,
894 base::Bind(&SSLClientSocketOpenSSL::OnHandshakeIOComplete,
[email protected]8420c6f2011-10-19 13:54:57895 base::Unretained(this)),
896 net_log_);
[email protected]170e76c2010-10-04 15:04:20897}
898
899int SSLClientSocketOpenSSL::DoVerifyCertComplete(int result) {
900 verifier_.reset();
901
902 if (result == OK) {
903 // TODO(joth): Work out if we need to remember the intermediate CA certs
904 // when the server sends them to us, and do so here.
[email protected]2907525c2010-10-08 15:53:52905 } else {
906 DVLOG(1) << "DoVerifyCertComplete error " << ErrorToString(result)
907 << " (" << result << ")";
[email protected]d518cd92010-09-29 12:27:44908 }
909
[email protected]170e76c2010-10-04 15:04:20910 completed_handshake_ = true;
[email protected]170e76c2010-10-04 15:04:20911 // Exit DoHandshakeLoop and return the result to the caller to Connect.
912 DCHECK_EQ(STATE_NONE, next_handshake_state_);
913 return result;
914}
915
[email protected]170e76c2010-10-04 15:04:20916X509Certificate* SSLClientSocketOpenSSL::UpdateServerCert() {
917 if (server_cert_)
918 return server_cert_;
919
[email protected]4b559b4d2011-04-14 17:37:14920 crypto::ScopedOpenSSL<X509, X509_free> cert(SSL_get_peer_certificate(ssl_));
[email protected]2907525c2010-10-08 15:53:52921 if (!cert.get()) {
[email protected]170e76c2010-10-04 15:04:20922 LOG(WARNING) << "SSL_get_peer_certificate returned NULL";
923 return NULL;
924 }
925
[email protected]2907525c2010-10-08 15:53:52926 // Unlike SSL_get_peer_certificate, SSL_get_peer_cert_chain does not
927 // increment the reference so sk_X509_free does not need to be called.
928 STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl_);
929 X509Certificate::OSCertHandles intermediates;
930 if (chain) {
931 for (int i = 0; i < sk_X509_num(chain); ++i)
932 intermediates.push_back(sk_X509_value(chain, i));
933 }
[email protected]72f508122011-07-19 05:12:17934 server_cert_ = X509Certificate::CreateFromHandle(cert.get(), intermediates);
[email protected]170e76c2010-10-04 15:04:20935 DCHECK(server_cert_);
[email protected]170e76c2010-10-04 15:04:20936
937 return server_cert_;
[email protected]d518cd92010-09-29 12:27:44938}
939
940bool SSLClientSocketOpenSSL::DoTransportIO() {
941 bool network_moved = false;
942 int nsent = BufferSend();
943 int nreceived = BufferRecv();
944 network_moved = (nsent > 0 || nreceived >= 0);
945 return network_moved;
946}
947
948int SSLClientSocketOpenSSL::BufferSend(void) {
949 if (transport_send_busy_)
950 return ERR_IO_PENDING;
951
952 if (!send_buffer_) {
953 // Get a fresh send buffer out of the send BIO.
954 size_t max_read = BIO_ctrl_pending(transport_bio_);
955 if (max_read > 0) {
956 send_buffer_ = new DrainableIOBuffer(new IOBuffer(max_read), max_read);
957 int read_bytes = BIO_read(transport_bio_, send_buffer_->data(), max_read);
958 DCHECK_GT(read_bytes, 0);
959 CHECK_EQ(static_cast<int>(max_read), read_bytes);
960 }
961 }
962
963 int rv = 0;
964 while (send_buffer_) {
[email protected]83039bb2011-12-09 18:43:55965 rv = transport_->socket()->Write(
966 send_buffer_,
967 send_buffer_->BytesRemaining(),
968 base::Bind(&SSLClientSocketOpenSSL::BufferSendComplete,
969 base::Unretained(this)));
[email protected]d518cd92010-09-29 12:27:44970 if (rv == ERR_IO_PENDING) {
971 transport_send_busy_ = true;
972 return rv;
973 }
974 TransportWriteComplete(rv);
975 }
976 return rv;
977}
978
979void SSLClientSocketOpenSSL::BufferSendComplete(int result) {
980 transport_send_busy_ = false;
981 TransportWriteComplete(result);
982 OnSendComplete(result);
983}
984
985void SSLClientSocketOpenSSL::TransportWriteComplete(int result) {
[email protected]abc7e06d2010-10-06 15:40:35986 DCHECK(ERR_IO_PENDING != result);
[email protected]d518cd92010-09-29 12:27:44987 if (result < 0) {
988 // Got a socket write error; close the BIO to indicate this upward.
[email protected]abc7e06d2010-10-06 15:40:35989 DVLOG(1) << "TransportWriteComplete error " << result;
[email protected]d518cd92010-09-29 12:27:44990 (void)BIO_shutdown_wr(transport_bio_);
991 send_buffer_ = NULL;
992 } else {
993 DCHECK(send_buffer_);
994 send_buffer_->DidConsume(result);
995 DCHECK_GE(send_buffer_->BytesRemaining(), 0);
996 if (send_buffer_->BytesRemaining() <= 0)
997 send_buffer_ = NULL;
998 }
999}
1000
1001int SSLClientSocketOpenSSL::BufferRecv(void) {
1002 if (transport_recv_busy_)
1003 return ERR_IO_PENDING;
1004
1005 size_t max_write = BIO_ctrl_get_write_guarantee(transport_bio_);
1006 if (max_write > kMaxRecvBufferSize)
1007 max_write = kMaxRecvBufferSize;
1008
1009 if (!max_write)
1010 return ERR_IO_PENDING;
1011
1012 recv_buffer_ = new IOBuffer(max_write);
[email protected]83039bb2011-12-09 18:43:551013 int rv = transport_->socket()->Read(
1014 recv_buffer_, max_write,
1015 base::Bind(&SSLClientSocketOpenSSL::BufferRecvComplete,
1016 base::Unretained(this)));
[email protected]d518cd92010-09-29 12:27:441017 if (rv == ERR_IO_PENDING) {
1018 transport_recv_busy_ = true;
1019 } else {
1020 TransportReadComplete(rv);
1021 }
1022 return rv;
1023}
1024
1025void SSLClientSocketOpenSSL::BufferRecvComplete(int result) {
1026 TransportReadComplete(result);
1027 OnRecvComplete(result);
1028}
1029
1030void SSLClientSocketOpenSSL::TransportReadComplete(int result) {
[email protected]abc7e06d2010-10-06 15:40:351031 DCHECK(ERR_IO_PENDING != result);
1032 if (result <= 0) {
1033 DVLOG(1) << "TransportReadComplete result " << result;
1034 // Received 0 (end of file) or an error. Either way, bubble it up to the
1035 // SSL layer via the BIO. TODO(joth): consider stashing the error code, to
1036 // relay up to the SSL socket client (i.e. via DoReadCallback).
1037 BIO_set_mem_eof_return(transport_bio_, 0);
1038 (void)BIO_shutdown_wr(transport_bio_);
1039 } else {
1040 DCHECK(recv_buffer_);
[email protected]d518cd92010-09-29 12:27:441041 int ret = BIO_write(transport_bio_, recv_buffer_->data(), result);
1042 // A write into a memory BIO should always succeed.
1043 CHECK_EQ(result, ret);
[email protected]d518cd92010-09-29 12:27:441044 }
1045 recv_buffer_ = NULL;
1046 transport_recv_busy_ = false;
1047}
1048
1049void SSLClientSocketOpenSSL::DoConnectCallback(int rv) {
[email protected]83039bb2011-12-09 18:43:551050 if (!user_connect_callback_.is_null()) {
[email protected]dbf036f2011-12-06 23:33:241051 CompletionCallback c = user_connect_callback_;
1052 user_connect_callback_.Reset();
1053 c.Run(rv > OK ? OK : rv);
1054 }
[email protected]d518cd92010-09-29 12:27:441055}
1056
1057void SSLClientSocketOpenSSL::OnHandshakeIOComplete(int result) {
1058 int rv = DoHandshakeLoop(result);
1059 if (rv != ERR_IO_PENDING) {
[email protected]d7fd1782011-02-08 19:16:431060 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv);
[email protected]d518cd92010-09-29 12:27:441061 DoConnectCallback(rv);
1062 }
1063}
1064
1065void SSLClientSocketOpenSSL::OnSendComplete(int result) {
[email protected]013c17c2012-01-21 19:09:011066 if (next_handshake_state_ == STATE_HANDSHAKE) {
[email protected]d518cd92010-09-29 12:27:441067 // In handshake phase.
1068 OnHandshakeIOComplete(result);
1069 return;
1070 }
1071
1072 // OnSendComplete may need to call DoPayloadRead while the renegotiation
1073 // handshake is in progress.
1074 int rv_read = ERR_IO_PENDING;
1075 int rv_write = ERR_IO_PENDING;
1076 bool network_moved;
1077 do {
1078 if (user_read_buf_)
1079 rv_read = DoPayloadRead();
1080 if (user_write_buf_)
1081 rv_write = DoPayloadWrite();
1082 network_moved = DoTransportIO();
1083 } while (rv_read == ERR_IO_PENDING &&
1084 rv_write == ERR_IO_PENDING &&
1085 network_moved);
1086
1087 if (user_read_buf_ && rv_read != ERR_IO_PENDING)
1088 DoReadCallback(rv_read);
1089 if (user_write_buf_ && rv_write != ERR_IO_PENDING)
1090 DoWriteCallback(rv_write);
1091}
1092
1093void SSLClientSocketOpenSSL::OnRecvComplete(int result) {
[email protected]013c17c2012-01-21 19:09:011094 if (next_handshake_state_ == STATE_HANDSHAKE) {
[email protected]d518cd92010-09-29 12:27:441095 // In handshake phase.
1096 OnHandshakeIOComplete(result);
1097 return;
1098 }
1099
1100 // Network layer received some data, check if client requested to read
1101 // decrypted data.
1102 if (!user_read_buf_)
1103 return;
1104
1105 int rv = DoReadLoop(result);
1106 if (rv != ERR_IO_PENDING)
1107 DoReadCallback(rv);
1108}
1109
1110bool SSLClientSocketOpenSSL::IsConnected() const {
1111 bool ret = completed_handshake_ && transport_->socket()->IsConnected();
1112 return ret;
1113}
1114
1115bool SSLClientSocketOpenSSL::IsConnectedAndIdle() const {
1116 bool ret = completed_handshake_ && transport_->socket()->IsConnectedAndIdle();
1117 return ret;
1118}
1119
1120int SSLClientSocketOpenSSL::GetPeerAddress(AddressList* addressList) const {
1121 return transport_->socket()->GetPeerAddress(addressList);
1122}
1123
[email protected]e7f74da2011-04-19 23:49:351124int SSLClientSocketOpenSSL::GetLocalAddress(IPEndPoint* addressList) const {
1125 return transport_->socket()->GetLocalAddress(addressList);
1126}
1127
[email protected]d518cd92010-09-29 12:27:441128const BoundNetLog& SSLClientSocketOpenSSL::NetLog() const {
1129 return net_log_;
1130}
1131
1132void SSLClientSocketOpenSSL::SetSubresourceSpeculation() {
1133 if (transport_.get() && transport_->socket()) {
1134 transport_->socket()->SetSubresourceSpeculation();
1135 } else {
1136 NOTREACHED();
1137 }
1138}
1139
1140void SSLClientSocketOpenSSL::SetOmniboxSpeculation() {
1141 if (transport_.get() && transport_->socket()) {
1142 transport_->socket()->SetOmniboxSpeculation();
1143 } else {
1144 NOTREACHED();
1145 }
1146}
1147
1148bool SSLClientSocketOpenSSL::WasEverUsed() const {
1149 if (transport_.get() && transport_->socket())
1150 return transport_->socket()->WasEverUsed();
1151
1152 NOTREACHED();
1153 return false;
1154}
1155
[email protected]7f7e92392010-10-26 18:29:291156bool SSLClientSocketOpenSSL::UsingTCPFastOpen() const {
1157 if (transport_.get() && transport_->socket())
1158 return transport_->socket()->UsingTCPFastOpen();
1159
1160 NOTREACHED();
1161 return false;
1162}
1163
[email protected]1e71d3072011-07-05 11:34:471164int64 SSLClientSocketOpenSSL::NumBytesRead() const {
1165 if (transport_.get() && transport_->socket())
1166 return transport_->socket()->NumBytesRead();
1167
1168 NOTREACHED();
1169 return -1;
1170}
1171
1172base::TimeDelta SSLClientSocketOpenSSL::GetConnectTimeMicros() const {
1173 if (transport_.get() && transport_->socket())
1174 return transport_->socket()->GetConnectTimeMicros();
1175
1176 NOTREACHED();
1177 return base::TimeDelta::FromMicroseconds(-1);
1178}
1179
[email protected]d518cd92010-09-29 12:27:441180// Socket methods
1181
1182int SSLClientSocketOpenSSL::Read(IOBuffer* buf,
1183 int buf_len,
[email protected]3f55aa12011-12-07 02:03:331184 const CompletionCallback& callback) {
1185 user_read_buf_ = buf;
1186 user_read_buf_len_ = buf_len;
1187
1188 int rv = DoReadLoop(OK);
1189
1190 if (rv == ERR_IO_PENDING) {
[email protected]d518cd92010-09-29 12:27:441191 user_read_callback_ = callback;
1192 } else {
1193 user_read_buf_ = NULL;
1194 user_read_buf_len_ = 0;
1195 }
1196
1197 return rv;
1198}
1199
1200int SSLClientSocketOpenSSL::DoReadLoop(int result) {
1201 if (result < 0)
1202 return result;
1203
1204 bool network_moved;
1205 int rv;
1206 do {
1207 rv = DoPayloadRead();
1208 network_moved = DoTransportIO();
1209 } while (rv == ERR_IO_PENDING && network_moved);
1210
1211 return rv;
1212}
1213
1214int SSLClientSocketOpenSSL::Write(IOBuffer* buf,
1215 int buf_len,
[email protected]83039bb2011-12-09 18:43:551216 const CompletionCallback& callback) {
[email protected]d518cd92010-09-29 12:27:441217 user_write_buf_ = buf;
1218 user_write_buf_len_ = buf_len;
1219
1220 int rv = DoWriteLoop(OK);
1221
1222 if (rv == ERR_IO_PENDING) {
1223 user_write_callback_ = callback;
1224 } else {
1225 user_write_buf_ = NULL;
1226 user_write_buf_len_ = 0;
1227 }
1228
1229 return rv;
1230}
1231
1232int SSLClientSocketOpenSSL::DoWriteLoop(int result) {
1233 if (result < 0)
1234 return result;
1235
1236 bool network_moved;
1237 int rv;
1238 do {
1239 rv = DoPayloadWrite();
1240 network_moved = DoTransportIO();
1241 } while (rv == ERR_IO_PENDING && network_moved);
1242
1243 return rv;
1244}
1245
1246bool SSLClientSocketOpenSSL::SetReceiveBufferSize(int32 size) {
1247 return transport_->socket()->SetReceiveBufferSize(size);
1248}
1249
1250bool SSLClientSocketOpenSSL::SetSendBufferSize(int32 size) {
1251 return transport_->socket()->SetSendBufferSize(size);
1252}
1253
1254int SSLClientSocketOpenSSL::DoPayloadRead() {
[email protected]4b559b4d2011-04-14 17:37:141255 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
[email protected]d518cd92010-09-29 12:27:441256 int rv = SSL_read(ssl_, user_read_buf_->data(), user_read_buf_len_);
1257 // We don't need to invalidate the non-client-authenticated SSL session
1258 // because the server will renegotiate anyway.
1259 if (client_auth_cert_needed_)
1260 return ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
1261
[email protected]1d872d32011-05-19 02:45:331262 if (rv >= 0) {
[email protected]267a0d66d2011-06-01 21:15:191263 net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv,
1264 user_read_buf_->data());
[email protected]d518cd92010-09-29 12:27:441265 return rv;
[email protected]1d872d32011-05-19 02:45:331266 }
[email protected]d518cd92010-09-29 12:27:441267
1268 int err = SSL_get_error(ssl_, rv);
[email protected]109805a2010-12-07 18:17:061269 return MapOpenSSLError(err, err_tracer);
[email protected]d518cd92010-09-29 12:27:441270}
1271
1272int SSLClientSocketOpenSSL::DoPayloadWrite() {
[email protected]4b559b4d2011-04-14 17:37:141273 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
[email protected]d518cd92010-09-29 12:27:441274 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_);
1275
[email protected]1d872d32011-05-19 02:45:331276 if (rv >= 0) {
[email protected]267a0d66d2011-06-01 21:15:191277 net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_SENT, rv,
1278 user_write_buf_->data());
[email protected]d518cd92010-09-29 12:27:441279 return rv;
[email protected]1d872d32011-05-19 02:45:331280 }
[email protected]d518cd92010-09-29 12:27:441281
1282 int err = SSL_get_error(ssl_, rv);
[email protected]109805a2010-12-07 18:17:061283 return MapOpenSSLError(err, err_tracer);
[email protected]d518cd92010-09-29 12:27:441284}
1285
[email protected]7e5dd49f2010-12-08 18:33:491286} // namespace net