Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(64)

Side by Side Diff: net/socket/ssl_client_socket_openssl.cc

Issue 177143004: OpenSSL: don't allow the server certificate to change during renegotiation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address wtc's comments. Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/socket/ssl_client_socket_openssl.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « net/socket/ssl_client_socket_openssl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698