Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // OpenSSL binding for SSLClientSocket. The class layout and general principle | 5 // OpenSSL binding for SSLClientSocket. The class layout and general principle |
| 6 // of operation is derived from SSLClientSocketNSS. | 6 // of operation is derived from SSLClientSocketNSS. |
| 7 | 7 |
| 8 #include "net/socket/ssl_client_socket_openssl.h" | 8 #include "net/socket/ssl_client_socket_openssl.h" |
| 9 | 9 |
| 10 #include <openssl/err.h> | 10 #include <openssl/err.h> |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 176 case SSL_R_SSLV3_ALERT_NO_CERTIFICATE: | 176 case SSL_R_SSLV3_ALERT_NO_CERTIFICATE: |
| 177 case SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER: | 177 case SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER: |
| 178 case SSL_R_TLSV1_ALERT_DECODE_ERROR: | 178 case SSL_R_TLSV1_ALERT_DECODE_ERROR: |
| 179 case SSL_R_TLSV1_ALERT_DECRYPTION_FAILED: | 179 case SSL_R_TLSV1_ALERT_DECRYPTION_FAILED: |
| 180 case SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION: | 180 case SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION: |
| 181 case SSL_R_TLSV1_ALERT_INTERNAL_ERROR: | 181 case SSL_R_TLSV1_ALERT_INTERNAL_ERROR: |
| 182 case SSL_R_TLSV1_ALERT_NO_RENEGOTIATION: | 182 case SSL_R_TLSV1_ALERT_NO_RENEGOTIATION: |
| 183 case SSL_R_TLSV1_ALERT_RECORD_OVERFLOW: | 183 case SSL_R_TLSV1_ALERT_RECORD_OVERFLOW: |
| 184 case SSL_R_TLSV1_ALERT_USER_CANCELLED: | 184 case SSL_R_TLSV1_ALERT_USER_CANCELLED: |
| 185 return ERR_SSL_PROTOCOL_ERROR; | 185 return ERR_SSL_PROTOCOL_ERROR; |
| 186 case SSL_R_CERTIFICATE_VERIFY_FAILED: | |
| 187 // The only way that the certificate verify callback can fail is if | |
| 188 // the leaf certificate changed during a renegotiation. | |
| 189 return ERR_SSL_SERVER_CERT_CHANGED; | |
| 186 default: | 190 default: |
| 187 LOG(WARNING) << "Unmapped error reason: " << ERR_GET_REASON(error_code); | 191 LOG(WARNING) << "Unmapped error reason: " << ERR_GET_REASON(error_code); |
| 188 return ERR_FAILED; | 192 return ERR_FAILED; |
| 189 } | 193 } |
| 190 } | 194 } |
| 191 | 195 |
| 192 // Converts an OpenSSL error code into a net error code, walking the OpenSSL | 196 // Converts an OpenSSL error code into a net error code, walking the OpenSSL |
| 193 // error stack if needed. Note that |tracer| is not currently used in the | 197 // error stack if needed. Note that |tracer| is not currently used in the |
| 194 // implementation, but is passed in anyway as this ensures the caller will clear | 198 // implementation, but is passed in anyway as this ensures the caller will clear |
| 195 // any residual codes left on the error stack. | 199 // any residual codes left on the error stack. |
| 196 int MapOpenSSLError(int err, const crypto::OpenSSLErrStackTracer& tracer) { | 200 int MapOpenSSLError(int err, const crypto::OpenSSLErrStackTracer& tracer) { |
| 197 switch (err) { | 201 switch (err) { |
| 198 case SSL_ERROR_WANT_READ: | 202 case SSL_ERROR_WANT_READ: |
| 199 case SSL_ERROR_WANT_WRITE: | 203 case SSL_ERROR_WANT_WRITE: |
| 200 return ERR_IO_PENDING; | 204 return ERR_IO_PENDING; |
| 201 case SSL_ERROR_SYSCALL: | 205 case SSL_ERROR_SYSCALL: |
| 202 LOG(ERROR) << "OpenSSL SYSCALL error, earliest error code in " | 206 LOG(ERROR) << "OpenSSL SYSCALL error, earliest error code in " |
| 203 "error queue: " << ERR_peek_error() << ", errno: " | 207 "error queue: " << ERR_peek_error() << ", errno: " |
| 204 << errno; | 208 << errno; |
| 205 return ERR_SSL_PROTOCOL_ERROR; | 209 return ERR_SSL_PROTOCOL_ERROR; |
| 206 case SSL_ERROR_SSL: | 210 case SSL_ERROR_SSL: |
| 207 return MapOpenSSLErrorSSL(); | 211 return MapOpenSSLErrorSSL(); |
| 208 default: | 212 default: |
| 209 // TODO(joth): Implement full mapping. | 213 // TODO(joth): Implement full mapping. |
| 210 LOG(WARNING) << "Unknown OpenSSL error " << err; | 214 LOG(WARNING) << "Unknown OpenSSL error " << err; |
| 211 return ERR_SSL_PROTOCOL_ERROR; | 215 return ERR_SSL_PROTOCOL_ERROR; |
| 212 } | 216 } |
| 213 } | 217 } |
| 214 | 218 |
| 215 // We do certificate verification after handshake, so we disable the default | |
| 216 // by registering a no-op verify function. | |
| 217 int NoOpVerifyCallback(X509_STORE_CTX*, void *) { | |
| 218 DVLOG(3) << "skipping cert verify"; | |
| 219 return 1; | |
| 220 } | |
| 221 | |
| 222 // Utility to construct the appropriate set & clear masks for use the OpenSSL | 219 // Utility to construct the appropriate set & clear masks for use the OpenSSL |
| 223 // options and mode configuration functions. (SSL_set_options etc) | 220 // options and mode configuration functions. (SSL_set_options etc) |
| 224 struct SslSetClearMask { | 221 struct SslSetClearMask { |
| 225 SslSetClearMask() : set_mask(0), clear_mask(0) {} | 222 SslSetClearMask() : set_mask(0), clear_mask(0) {} |
| 226 void ConfigureFlag(long flag, bool state) { | 223 void ConfigureFlag(long flag, bool state) { |
| 227 (state ? set_mask : clear_mask) |= flag; | 224 (state ? set_mask : clear_mask) |= flag; |
| 228 // Make sure we haven't got any intersection in the set & clear options. | 225 // Make sure we haven't got any intersection in the set & clear options. |
| 229 DCHECK_EQ(0, set_mask & clear_mask) << flag << ":" << state; | 226 DCHECK_EQ(0, set_mask & clear_mask) << flag << ":" << state; |
| 230 } | 227 } |
| 231 long set_mask; | 228 long set_mask; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 263 | 260 |
| 264 private: | 261 private: |
| 265 friend struct DefaultSingletonTraits<SSLContext>; | 262 friend struct DefaultSingletonTraits<SSLContext>; |
| 266 | 263 |
| 267 SSLContext() { | 264 SSLContext() { |
| 268 crypto::EnsureOpenSSLInit(); | 265 crypto::EnsureOpenSSLInit(); |
| 269 ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0); | 266 ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0); |
| 270 DCHECK_NE(ssl_socket_data_index_, -1); | 267 DCHECK_NE(ssl_socket_data_index_, -1); |
| 271 ssl_ctx_.reset(SSL_CTX_new(SSLv23_client_method())); | 268 ssl_ctx_.reset(SSL_CTX_new(SSLv23_client_method())); |
| 272 session_cache_.Reset(ssl_ctx_.get(), kDefaultSessionCacheConfig); | 269 session_cache_.Reset(ssl_ctx_.get(), kDefaultSessionCacheConfig); |
| 273 SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), NoOpVerifyCallback, NULL); | 270 SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), CertVerifyCallback, NULL); |
| 274 SSL_CTX_set_client_cert_cb(ssl_ctx_.get(), ClientCertCallback); | 271 SSL_CTX_set_client_cert_cb(ssl_ctx_.get(), ClientCertCallback); |
| 275 SSL_CTX_set_channel_id_cb(ssl_ctx_.get(), ChannelIDCallback); | 272 SSL_CTX_set_channel_id_cb(ssl_ctx_.get(), ChannelIDCallback); |
| 273 SSL_CTX_set_verify(ssl_ctx_.get(), SSL_VERIFY_PEER, NULL); | |
| 276 #if defined(OPENSSL_NPN_NEGOTIATED) | 274 #if defined(OPENSSL_NPN_NEGOTIATED) |
| 277 // TODO(kristianm): Only select this if ssl_config_.next_proto is not empty. | 275 // TODO(kristianm): Only select this if ssl_config_.next_proto is not empty. |
| 278 // It would be better if the callback were not a global setting, | 276 // It would be better if the callback were not a global setting, |
| 279 // but that is an OpenSSL issue. | 277 // but that is an OpenSSL issue. |
| 280 SSL_CTX_set_next_proto_select_cb(ssl_ctx_.get(), SelectNextProtoCallback, | 278 SSL_CTX_set_next_proto_select_cb(ssl_ctx_.get(), SelectNextProtoCallback, |
| 281 NULL); | 279 NULL); |
| 282 #endif | 280 #endif |
| 283 } | 281 } |
| 284 | 282 |
| 285 static std::string GetSessionCacheKey(const SSL* ssl) { | 283 static std::string GetSessionCacheKey(const SSL* ssl) { |
| 286 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); | 284 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); |
| 287 DCHECK(socket); | 285 DCHECK(socket); |
| 288 return GetSocketSessionCacheKey(*socket); | 286 return GetSocketSessionCacheKey(*socket); |
| 289 } | 287 } |
| 290 | 288 |
| 291 static SSLSessionCacheOpenSSL::Config kDefaultSessionCacheConfig; | 289 static SSLSessionCacheOpenSSL::Config kDefaultSessionCacheConfig; |
| 292 | 290 |
| 293 static int ClientCertCallback(SSL* ssl, X509** x509, EVP_PKEY** pkey) { | 291 static int ClientCertCallback(SSL* ssl, X509** x509, EVP_PKEY** pkey) { |
| 294 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); | 292 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); |
| 295 CHECK(socket); | 293 CHECK(socket); |
| 296 return socket->ClientCertRequestCallback(ssl, x509, pkey); | 294 return socket->ClientCertRequestCallback(ssl, x509, pkey); |
| 297 } | 295 } |
| 298 | 296 |
| 299 static void ChannelIDCallback(SSL* ssl, EVP_PKEY** pkey) { | 297 static void ChannelIDCallback(SSL* ssl, EVP_PKEY** pkey) { |
| 300 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); | 298 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); |
| 301 CHECK(socket); | 299 CHECK(socket); |
| 302 socket->ChannelIDRequestCallback(ssl, pkey); | 300 socket->ChannelIDRequestCallback(ssl, pkey); |
| 303 } | 301 } |
| 304 | 302 |
| 303 static int CertVerifyCallback(X509_STORE_CTX *store_ctx, void *arg) { | |
| 304 SSL* ssl = reinterpret_cast<SSL*>(X509_STORE_CTX_get_ex_data( | |
| 305 store_ctx, SSL_get_ex_data_X509_STORE_CTX_idx())); | |
| 306 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); | |
| 307 CHECK(socket); | |
| 308 | |
| 309 return socket->CertVerifyCallback(store_ctx); | |
| 310 } | |
| 311 | |
| 305 static int SelectNextProtoCallback(SSL* ssl, | 312 static int SelectNextProtoCallback(SSL* ssl, |
| 306 unsigned char** out, unsigned char* outlen, | 313 unsigned char** out, unsigned char* outlen, |
| 307 const unsigned char* in, | 314 const unsigned char* in, |
| 308 unsigned int inlen, void* arg) { | 315 unsigned int inlen, void* arg) { |
| 309 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); | 316 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); |
| 310 return socket->SelectNextProtoCallback(out, outlen, in, inlen); | 317 return socket->SelectNextProtoCallback(out, outlen, in, inlen); |
| 311 } | 318 } |
| 312 | 319 |
| 313 // This is the index used with SSL_get_ex_data to retrieve the owner | 320 // This is the index used with SSL_get_ex_data to retrieve the owner |
| 314 // SSLClientSocketOpenSSL object from an SSL instance. | 321 // SSLClientSocketOpenSSL object from an SSL instance. |
| (...skipping 1050 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1365 crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( | 1372 crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( |
| 1366 ServerBoundCertService::kEPKIPassword, | 1373 ServerBoundCertService::kEPKIPassword, |
| 1367 encrypted_private_key_info, | 1374 encrypted_private_key_info, |
| 1368 subject_public_key_info)); | 1375 subject_public_key_info)); |
| 1369 if (!ec_private_key) | 1376 if (!ec_private_key) |
| 1370 return; | 1377 return; |
| 1371 set_channel_id_sent(true); | 1378 set_channel_id_sent(true); |
| 1372 *pkey = EVP_PKEY_dup(ec_private_key->key()); | 1379 *pkey = EVP_PKEY_dup(ec_private_key->key()); |
| 1373 } | 1380 } |
| 1374 | 1381 |
| 1382 int SSLClientSocketOpenSSL::CertVerifyCallback(X509_STORE_CTX* store_ctx) { | |
| 1383 if (!completed_handshake_) { | |
| 1384 // If the first handshake hasn't completed then we accept any certificates | |
| 1385 // because we verify after the handshake. | |
| 1386 return 1; | |
| 1387 } | |
| 1388 | |
| 1389 std::string der_current_cert; | |
| 1390 if (!X509Certificate::GetDEREncoded(server_cert_->os_cert_handle(), | |
| 1391 &der_current_cert)) { | |
| 1392 LOG(ERROR) << "Failed to get current certificate in DER form"; | |
| 1393 return 0; | |
| 1394 } | |
| 1395 | |
| 1396 X509* leaf_cert = sk_X509_value(store_ctx->chain, 0); | |
| 1397 int len = i2d_X509(leaf_cert, NULL); | |
| 1398 if (len < 0) { | |
| 1399 LOG(ERROR) << "Failed to marshal certificate from renegotiation"; | |
| 1400 return 0; | |
| 1401 } | |
| 1402 | |
| 1403 scoped_ptr<uint8[]> der_leaf_cert(new uint8[len]); | |
| 1404 uint8 *outp = der_leaf_cert.get(); | |
| 1405 len = i2d_X509(leaf_cert, &outp); | |
| 1406 | |
| 1407 if (static_cast<size_t>(len) == der_current_cert.size() && | |
| 1408 memcmp(der_leaf_cert.get(), | |
| 1409 der_current_cert.data(), | |
| 1410 der_current_cert.size()) == 0) { | |
| 1411 // The certificates match so the renegotiation can continue. | |
| 1412 return 1; | |
| 1413 } | |
|
Ryan Sleevi
2014/02/27 22:43:40
Why do this? Why not simply use
if (!completed_ha
agl
2014/02/27 22:57:10
Yep, that works. Thanks!
| |
| 1414 | |
| 1415 LOG(ERROR) << "Server certificate changed between handshakes"; | |
| 1416 return 0; | |
| 1417 } | |
| 1418 | |
| 1375 // SelectNextProtoCallback is called by OpenSSL during the handshake. If the | 1419 // SelectNextProtoCallback is called by OpenSSL during the handshake. If the |
| 1376 // server supports NPN, selects a protocol from the list that the server | 1420 // server supports NPN, selects a protocol from the list that the server |
| 1377 // provides. According to third_party/openssl/openssl/ssl/ssl_lib.c, the | 1421 // provides. According to third_party/openssl/openssl/ssl/ssl_lib.c, the |
| 1378 // callback can assume that |in| is syntactically valid. | 1422 // callback can assume that |in| is syntactically valid. |
| 1379 int SSLClientSocketOpenSSL::SelectNextProtoCallback(unsigned char** out, | 1423 int SSLClientSocketOpenSSL::SelectNextProtoCallback(unsigned char** out, |
| 1380 unsigned char* outlen, | 1424 unsigned char* outlen, |
| 1381 const unsigned char* in, | 1425 const unsigned char* in, |
| 1382 unsigned int inlen) { | 1426 unsigned int inlen) { |
| 1383 #if defined(OPENSSL_NPN_NEGOTIATED) | 1427 #if defined(OPENSSL_NPN_NEGOTIATED) |
| 1384 if (ssl_config_.next_protos.empty()) { | 1428 if (ssl_config_.next_protos.empty()) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1418 } | 1462 } |
| 1419 | 1463 |
| 1420 npn_proto_.assign(reinterpret_cast<const char*>(*out), *outlen); | 1464 npn_proto_.assign(reinterpret_cast<const char*>(*out), *outlen); |
| 1421 server_protos_.assign(reinterpret_cast<const char*>(in), inlen); | 1465 server_protos_.assign(reinterpret_cast<const char*>(in), inlen); |
| 1422 DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_; | 1466 DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_; |
| 1423 #endif | 1467 #endif |
| 1424 return SSL_TLSEXT_ERR_OK; | 1468 return SSL_TLSEXT_ERR_OK; |
| 1425 } | 1469 } |
| 1426 | 1470 |
| 1427 } // namespace net | 1471 } // namespace net |
| OLD | NEW |