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

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

Issue 1360633002: Implement Token Binding negotiation TLS extension (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@test-server-flags
Patch Set: update to latest version of tb nego spec; tweak SSLConfig Created 5 years, 1 month 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
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 <errno.h> 10 #include <errno.h>
11 #include <openssl/bio.h> 11 #include <openssl/bio.h>
12 #include <openssl/bytestring.h>
12 #include <openssl/err.h> 13 #include <openssl/err.h>
14 #include <openssl/evp.h>
13 #include <openssl/mem.h> 15 #include <openssl/mem.h>
14 #include <openssl/ssl.h> 16 #include <openssl/ssl.h>
15 #include <string.h> 17 #include <string.h>
16 18
17 #include "base/bind.h" 19 #include "base/bind.h"
18 #include "base/callback_helpers.h" 20 #include "base/callback_helpers.h"
19 #include "base/lazy_instance.h" 21 #include "base/lazy_instance.h"
20 #include "base/memory/singleton.h" 22 #include "base/memory/singleton.h"
21 #include "base/metrics/histogram_macros.h" 23 #include "base/metrics/histogram_macros.h"
22 #include "base/profiler/scoped_tracker.h" 24 #include "base/profiler/scoped_tracker.h"
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 // overlap with any value of the net::Error range, including net::OK). 77 // overlap with any value of the net::Error range, including net::OK).
76 const int kNoPendingResult = 1; 78 const int kNoPendingResult = 1;
77 79
78 // If a client doesn't have a list of protocols that it supports, but 80 // If a client doesn't have a list of protocols that it supports, but
79 // the server supports NPN, choosing "http/1.1" is the best answer. 81 // the server supports NPN, choosing "http/1.1" is the best answer.
80 const char kDefaultSupportedNPNProtocol[] = "http/1.1"; 82 const char kDefaultSupportedNPNProtocol[] = "http/1.1";
81 83
82 // Default size of the internal BoringSSL buffers. 84 // Default size of the internal BoringSSL buffers.
83 const int KDefaultOpenSSLBufferSize = 17 * 1024; 85 const int KDefaultOpenSSLBufferSize = 17 * 1024;
84 86
87 // TLS extension number use for Token Binding.
88 const unsigned int kTbExtNum = 30033;
89
90 // Token Binding ProtocolVersions supported.
91 const uint8_t kTbProtocolVersionMajor = 0;
92 const uint8_t kTbProtocolVersionMinor = 3;
93 const uint8_t kTbMinProtocolVersionMajor = 0;
94 const uint8_t kTbMinProtocolVersionMinor = 2;
95
85 void FreeX509Stack(STACK_OF(X509)* ptr) { 96 void FreeX509Stack(STACK_OF(X509)* ptr) {
86 sk_X509_pop_free(ptr, X509_free); 97 sk_X509_pop_free(ptr, X509_free);
87 } 98 }
88 99
89 using ScopedX509Stack = crypto::ScopedOpenSSL<STACK_OF(X509), FreeX509Stack>; 100 using ScopedX509Stack = crypto::ScopedOpenSSL<STACK_OF(X509), FreeX509Stack>;
90 101
91 // Used for encoding the |connection_status| field of an SSLInfo object. 102 // Used for encoding the |connection_status| field of an SSLInfo object.
92 int EncodeSSLConnectionStatus(uint16 cipher_suite, 103 int EncodeSSLConnectionStatus(uint16 cipher_suite,
93 int compression, 104 int compression,
94 int version) { 105 int version) {
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 // Note that SSL_OP_DISABLE_NPN is used to disable NPN if 247 // Note that SSL_OP_DISABLE_NPN is used to disable NPN if
237 // ssl_config_.next_proto is empty. 248 // ssl_config_.next_proto is empty.
238 SSL_CTX_set_next_proto_select_cb(ssl_ctx_.get(), SelectNextProtoCallback, 249 SSL_CTX_set_next_proto_select_cb(ssl_ctx_.get(), SelectNextProtoCallback,
239 NULL); 250 NULL);
240 251
241 // Disable the internal session cache. Session caching is handled 252 // Disable the internal session cache. Session caching is handled
242 // externally (i.e. by SSLClientSessionCacheOpenSSL). 253 // externally (i.e. by SSLClientSessionCacheOpenSSL).
243 SSL_CTX_set_session_cache_mode( 254 SSL_CTX_set_session_cache_mode(
244 ssl_ctx_.get(), SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL); 255 ssl_ctx_.get(), SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL);
245 SSL_CTX_sess_set_new_cb(ssl_ctx_.get(), NewSessionCallback); 256 SSL_CTX_sess_set_new_cb(ssl_ctx_.get(), NewSessionCallback);
257
258 if (!RegisterTokenBindingExtensionCallbacks(ssl_ctx_.get()))
259 NOTREACHED();
246 } 260 }
247 261
248 static int ClientCertRequestCallback(SSL* ssl, void* arg) { 262 static int ClientCertRequestCallback(SSL* ssl, void* arg) {
249 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); 263 SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl);
250 DCHECK(socket); 264 DCHECK(socket);
251 return socket->ClientCertRequestCallback(ssl); 265 return socket->ClientCertRequestCallback(ssl);
252 } 266 }
253 267
254 static int CertVerifyCallback(X509_STORE_CTX *store_ctx, void *arg) { 268 static int CertVerifyCallback(X509_STORE_CTX *store_ctx, void *arg) {
255 SSL* ssl = reinterpret_cast<SSL*>(X509_STORE_CTX_get_ex_data( 269 SSL* ssl = reinterpret_cast<SSL*>(X509_STORE_CTX_get_ex_data(
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 pending_read_error_(kNoPendingResult), 438 pending_read_error_(kNoPendingResult),
425 pending_read_ssl_error_(SSL_ERROR_NONE), 439 pending_read_ssl_error_(SSL_ERROR_NONE),
426 transport_read_error_(OK), 440 transport_read_error_(OK),
427 transport_write_error_(OK), 441 transport_write_error_(OK),
428 server_cert_chain_(new PeerCertificateChain(NULL)), 442 server_cert_chain_(new PeerCertificateChain(NULL)),
429 completed_connect_(false), 443 completed_connect_(false),
430 was_ever_used_(false), 444 was_ever_used_(false),
431 cert_verifier_(context.cert_verifier), 445 cert_verifier_(context.cert_verifier),
432 cert_transparency_verifier_(context.cert_transparency_verifier), 446 cert_transparency_verifier_(context.cert_transparency_verifier),
433 channel_id_service_(context.channel_id_service), 447 channel_id_service_(context.channel_id_service),
448 tb_was_negotiated_(false),
449 tb_negotiated_param_(TB_PARAM_ECDSAP256),
434 ssl_(NULL), 450 ssl_(NULL),
435 transport_bio_(NULL), 451 transport_bio_(NULL),
436 transport_(transport_socket.Pass()), 452 transport_(transport_socket.Pass()),
437 host_and_port_(host_and_port), 453 host_and_port_(host_and_port),
438 ssl_config_(ssl_config), 454 ssl_config_(ssl_config),
439 ssl_session_cache_shard_(context.ssl_session_cache_shard), 455 ssl_session_cache_shard_(context.ssl_session_cache_shard),
440 next_handshake_state_(STATE_NONE), 456 next_handshake_state_(STATE_NONE),
441 disconnected_(false), 457 disconnected_(false),
442 npn_status_(kNextProtoUnsupported), 458 npn_status_(kNextProtoUnsupported),
443 channel_id_sent_(false), 459 channel_id_sent_(false),
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 616
601 cert_authorities_.clear(); 617 cert_authorities_.clear();
602 cert_key_types_.clear(); 618 cert_key_types_.clear();
603 619
604 start_cert_verification_time_ = base::TimeTicks(); 620 start_cert_verification_time_ = base::TimeTicks();
605 621
606 npn_status_ = kNextProtoUnsupported; 622 npn_status_ = kNextProtoUnsupported;
607 npn_proto_.clear(); 623 npn_proto_.clear();
608 624
609 channel_id_sent_ = false; 625 channel_id_sent_ = false;
626 tb_was_negotiated_ = false;
610 session_pending_ = false; 627 session_pending_ = false;
611 certificate_verified_ = false; 628 certificate_verified_ = false;
612 channel_id_request_.Cancel(); 629 channel_id_request_.Cancel();
613 ssl_failure_state_ = SSL_FAILURE_NONE; 630 ssl_failure_state_ = SSL_FAILURE_NONE;
614 631
615 private_key_.reset(); 632 private_key_.reset();
616 signature_result_ = kNoPendingResult; 633 signature_result_ = kNoPendingResult;
617 signature_.clear(); 634 signature_.clear();
618 } 635 }
619 636
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
697 ssl_info->cert = server_cert_verify_result_.verified_cert; 714 ssl_info->cert = server_cert_verify_result_.verified_cert;
698 ssl_info->unverified_cert = server_cert_; 715 ssl_info->unverified_cert = server_cert_;
699 ssl_info->cert_status = server_cert_verify_result_.cert_status; 716 ssl_info->cert_status = server_cert_verify_result_.cert_status;
700 ssl_info->is_issued_by_known_root = 717 ssl_info->is_issued_by_known_root =
701 server_cert_verify_result_.is_issued_by_known_root; 718 server_cert_verify_result_.is_issued_by_known_root;
702 ssl_info->public_key_hashes = 719 ssl_info->public_key_hashes =
703 server_cert_verify_result_.public_key_hashes; 720 server_cert_verify_result_.public_key_hashes;
704 ssl_info->client_cert_sent = 721 ssl_info->client_cert_sent =
705 ssl_config_.send_client_cert && ssl_config_.client_cert.get(); 722 ssl_config_.send_client_cert && ssl_config_.client_cert.get();
706 ssl_info->channel_id_sent = channel_id_sent_; 723 ssl_info->channel_id_sent = channel_id_sent_;
724 ssl_info->token_binding_negotiated = tb_was_negotiated_;
725 ssl_info->token_binding_key_param = tb_negotiated_param_;
707 ssl_info->pinning_failure_log = pinning_failure_log_; 726 ssl_info->pinning_failure_log = pinning_failure_log_;
708 727
709 AddSCTInfoToSSLInfo(ssl_info); 728 AddSCTInfoToSSLInfo(ssl_info);
710 729
711 const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl_); 730 const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl_);
712 CHECK(cipher); 731 CHECK(cipher);
713 ssl_info->security_bits = SSL_CIPHER_get_bits(cipher, NULL); 732 ssl_info->security_bits = SSL_CIPHER_get_bits(cipher, NULL);
714 ssl_info->key_exchange_info = 733 ssl_info->key_exchange_info =
715 SSL_SESSION_get_key_exchange_info(SSL_get_session(ssl_)); 734 SSL_SESSION_get_key_exchange_info(SSL_get_session(ssl_));
716 735
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after
1096 1115
1097 int SSLClientSocketOpenSSL::DoHandshakeComplete(int result) { 1116 int SSLClientSocketOpenSSL::DoHandshakeComplete(int result) {
1098 if (result < 0) 1117 if (result < 0)
1099 return result; 1118 return result;
1100 1119
1101 if (ssl_config_.version_fallback && 1120 if (ssl_config_.version_fallback &&
1102 ssl_config_.version_max < ssl_config_.version_fallback_min) { 1121 ssl_config_.version_max < ssl_config_.version_fallback_min) {
1103 return ERR_SSL_FALLBACK_BEYOND_MINIMUM_VERSION; 1122 return ERR_SSL_FALLBACK_BEYOND_MINIMUM_VERSION;
1104 } 1123 }
1105 1124
1125 // Check that if token binding was negotiated, then extended master secret
1126 // must also be negotiated.
1127 if (tb_was_negotiated_ && !SSL_get_extms_support(ssl_))
1128 return ERR_SSL_PROTOCOL_ERROR;
1129
1106 // SSL handshake is completed. If NPN wasn't negotiated, see if ALPN was. 1130 // SSL handshake is completed. If NPN wasn't negotiated, see if ALPN was.
1107 if (npn_status_ == kNextProtoUnsupported) { 1131 if (npn_status_ == kNextProtoUnsupported) {
1108 const uint8_t* alpn_proto = NULL; 1132 const uint8_t* alpn_proto = NULL;
1109 unsigned alpn_len = 0; 1133 unsigned alpn_len = 0;
1110 SSL_get0_alpn_selected(ssl_, &alpn_proto, &alpn_len); 1134 SSL_get0_alpn_selected(ssl_, &alpn_proto, &alpn_len);
1111 if (alpn_len > 0) { 1135 if (alpn_len > 0) {
1112 npn_proto_.assign(reinterpret_cast<const char*>(alpn_proto), alpn_len); 1136 npn_proto_.assign(reinterpret_cast<const char*>(alpn_proto), alpn_len);
1113 npn_status_ = kNextProtoNegotiated; 1137 npn_status_ = kNextProtoNegotiated;
1114 set_negotiation_extension(kExtensionALPN); 1138 set_negotiation_extension(kExtensionALPN);
1115 } 1139 }
(...skipping 942 matching lines...) Expand 10 before | Expand all | Expand 10 after
2058 result.append("deprecated"); 2082 result.append("deprecated");
2059 2083
2060 result.append("/"); 2084 result.append("/");
2061 if (ssl_config_.channel_id_enabled) 2085 if (ssl_config_.channel_id_enabled)
2062 result.append("channelid"); 2086 result.append("channelid");
2063 2087
2064 return result; 2088 return result;
2065 } 2089 }
2066 2090
2067 bool SSLClientSocketOpenSSL::IsRenegotiationAllowed() const { 2091 bool SSLClientSocketOpenSSL::IsRenegotiationAllowed() const {
2092 if (tb_was_negotiated_)
2093 return false;
2094
2068 if (npn_status_ == kNextProtoUnsupported) 2095 if (npn_status_ == kNextProtoUnsupported)
2069 return ssl_config_.renego_allowed_default; 2096 return ssl_config_.renego_allowed_default;
2070 2097
2071 NextProto next_proto = NextProtoFromString(npn_proto_); 2098 NextProto next_proto = NextProtoFromString(npn_proto_);
2072 for (NextProto allowed : ssl_config_.renego_allowed_for_protos) { 2099 for (NextProto allowed : ssl_config_.renego_allowed_for_protos) {
2073 if (next_proto == allowed) 2100 if (next_proto == allowed)
2074 return true; 2101 return true;
2075 } 2102 }
2076 return false; 2103 return false;
2077 } 2104 }
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
2158 if (next_handshake_state_ == STATE_HANDSHAKE) { 2185 if (next_handshake_state_ == STATE_HANDSHAKE) {
2159 OnHandshakeIOComplete(signature_result_); 2186 OnHandshakeIOComplete(signature_result_);
2160 return; 2187 return;
2161 } 2188 }
2162 2189
2163 // During a renegotiation, either Read or Write calls may be blocked on an 2190 // During a renegotiation, either Read or Write calls may be blocked on an
2164 // asynchronous private key operation. 2191 // asynchronous private key operation.
2165 PumpReadWriteEvents(); 2192 PumpReadWriteEvents();
2166 } 2193 }
2167 2194
2195 // static
2196 bool SSLClientSocketOpenSSL::RegisterTokenBindingExtensionCallbacks(
2197 SSL_CTX* ssl_ctx) {
2198 return SSL_CTX_add_client_custom_ext(
2199 ssl_ctx, kTbExtNum, &TokenBindingAddCallback,
2200 &TokenBindingFreeCallback, nullptr, &TokenBindingParseCallback,
2201 nullptr) != 0;
2202 }
2203
2204 namespace {
2205 CBB* CBB_new(size_t initial_capacity) {
2206 CBB* ret;
2207 ret = reinterpret_cast<CBB*>(OPENSSL_malloc(sizeof(CBB)));
2208 if (ret == NULL)
2209 return NULL;
2210 if (!CBB_init(ret, initial_capacity))
2211 OPENSSL_free(ret);
2212 return ret;
2213 }
2214
2215 void CBB_free(CBB* cbb) {
2216 if (cbb == NULL)
2217 return;
2218 CBB_cleanup(cbb);
2219 OPENSSL_free(cbb);
2220 }
2221 }
davidben 2015/11/04 00:40:36 What's wrong with class ScopedCBB { public: Sc
nharper 2015/11/04 02:28:04 Nothing's wrong with it. I thought you were sugges
2222
2223 using ScopedCBB = crypto::ScopedOpenSSL<CBB, CBB_free>;
2224
2225 int SSLClientSocketOpenSSL::TokenBindingAdd(const uint8_t** out,
2226 size_t* out_len,
2227 int* out_alert_value) {
2228 if (!ssl_config_.token_binding_enabled ||
2229 ssl_config_.token_binding_params.empty()) {
2230 return 0;
2231 }
2232 ScopedCBB output(CBB_new(7));
2233 CBB parameters_list;
2234 int retval = -1;
2235 if (!CBB_add_u8(output.get(), kTbProtocolVersionMajor) ||
2236 !CBB_add_u8(output.get(), kTbProtocolVersionMinor) ||
2237 !CBB_add_u8_length_prefixed(output.get(), &parameters_list)) {
2238 return 0;
2239 }
2240 for (size_t i = 0; i < ssl_config_.token_binding_params.size(); ++i) {
2241 if (!CBB_add_u8(&parameters_list, ssl_config_.token_binding_params[i]))
2242 return 0;
2243 }
2244 // |*out| will be freed by TokenBindingFreeCallback.
2245 if (!CBB_finish(output.get(), const_cast<uint8_t**>(out), out_len))
2246 return 0;
2247
2248 retval = 1;
2249
2250 if (retval == -1)
2251 *out_alert_value = SSL_AD_INTERNAL_ERROR;
2252 return retval;
2253 }
2254
2255 int SSLClientSocketOpenSSL::TokenBindingParse(const uint8_t* contents,
2256 size_t contents_len,
2257 int* out_alert_value) {
2258 if (completed_connect_) {
2259 // Token Binding may only be negotiated on the initial handshake.
2260 *out_alert_value = SSL_AD_ILLEGAL_PARAMETER;
2261 return 0;
2262 }
2263
2264 CBS extension;
2265 CBS_init(&extension, contents, contents_len);
2266
2267 CBS parameters_list;
2268 uint8_t version_major, version_minor, param;
2269 if (!CBS_get_u8(&extension, &version_major) ||
2270 !CBS_get_u8(&extension, &version_minor) ||
2271 !CBS_get_u8_length_prefixed(&extension, &parameters_list) ||
2272 !CBS_get_u8(&parameters_list, &param) || CBS_len(&extension) > 0 ||
2273 CBS_len(&parameters_list) > 0) {
davidben 2015/11/04 00:40:36 Super nitpicky nit: I think it's mildly better to
nharper 2015/11/04 02:28:04 Done.
2274 *out_alert_value = SSL_AD_DECODE_ERROR;
2275 return 0;
2276 }
2277 // The server-negotiated version must be less than or equal to our version.
2278 if (version_major > kTbProtocolVersionMajor ||
2279 (version_minor > kTbProtocolVersionMinor &&
2280 version_major == kTbProtocolVersionMajor)) {
2281 *out_alert_value = SSL_AD_ILLEGAL_PARAMETER;
2282 return 0;
2283 }
2284 // If the version the server negotiated is older than we support, don't fail
2285 // parsing the extension, but also don't set |negotiated_|.
2286 if (version_major < kTbMinProtocolVersionMajor ||
2287 (version_minor < kTbMinProtocolVersionMinor &&
2288 version_major == kTbMinProtocolVersionMajor)) {
2289 return 1;
2290 }
2291
2292 for (size_t i = 0; i < ssl_config_.token_binding_params.size(); ++i) {
2293 if (param == ssl_config_.token_binding_params[i]) {
2294 tb_negotiated_param_ = ssl_config_.token_binding_params[i];
2295 tb_was_negotiated_ = true;
2296 return 1;
2297 }
2298 }
davidben 2015/11/04 00:40:36 Optional: std::find I think works here too. Might
nharper 2015/11/04 02:28:04 std::find works, but the code is just as long (or
2299
2300 *out_alert_value = SSL_AD_ILLEGAL_PARAMETER;
2301 return 0;
2302 }
2303
2304 // static
2305 int SSLClientSocketOpenSSL::TokenBindingAddCallback(
2306 SSL* ssl,
2307 unsigned int extension_value,
2308 const uint8_t** out,
2309 size_t* out_len,
2310 int* out_alert_value,
2311 void* add_arg) {
davidben 2015/11/04 00:40:35 Most of the other FooCallback wrappers were static
nharper 2015/11/04 02:28:04 I inlined Register in SSLContext. Are you also sug
davidben 2015/11/04 17:40:13 Yeah. Doesn't really matter, but it's more consist
nharper 2015/11/04 19:43:18 I moved them into SSLContext to go with the rest o
2312 DCHECK_EQ(extension_value, kTbExtNum);
2313 SSLClientSocketOpenSSL* socket =
2314 SSLClientSocketOpenSSL::SSLContext::GetInstance()->GetClientSocketFromSSL(
2315 ssl);
2316 return socket->TokenBindingAdd(out, out_len, out_alert_value);
2317 }
2318
2319 // static
2320 void SSLClientSocketOpenSSL::TokenBindingFreeCallback(SSL* ssl,
2321 unsigned extension_value,
2322 const uint8_t* out,
2323 void* add_arg) {
2324 DCHECK_EQ(extension_value, kTbExtNum);
2325 OPENSSL_free(const_cast<unsigned char*>(out));
2326 }
2327
2328 // static
2329 int SSLClientSocketOpenSSL::TokenBindingParseCallback(
2330 SSL* ssl,
2331 unsigned int extension_value,
2332 const uint8_t* contents,
2333 size_t contents_len,
2334 int* out_alert_value,
2335 void* parse_arg) {
2336 DCHECK_EQ(extension_value, kTbExtNum);
2337 SSLClientSocketOpenSSL* socket =
2338 SSLClientSocketOpenSSL::SSLContext::GetInstance()->GetClientSocketFromSSL(
2339 ssl);
2340 return socket->TokenBindingParse(contents, contents_len, out_alert_value);
2341 }
2342
2168 } // namespace net 2343 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698