Patch 3/3 to get WebScheduler via WebThread
[chromium-blink-merge.git] / net / socket / ssl_client_socket.cc
blobf333cb8ec89aaffe55d8f663a7b74e4ad100f119
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
3 // found in the LICENSE file.
5 #include "net/socket/ssl_client_socket.h"
7 #include "base/metrics/histogram.h"
8 #include "base/metrics/sparse_histogram.h"
9 #include "base/strings/string_util.h"
10 #include "crypto/ec_private_key.h"
11 #include "net/base/connection_type_histograms.h"
12 #include "net/base/net_errors.h"
13 #include "net/ssl/channel_id_service.h"
14 #include "net/ssl/ssl_cipher_suite_names.h"
15 #include "net/ssl/ssl_config_service.h"
16 #include "net/ssl/ssl_connection_status_flags.h"
18 namespace net {
20 SSLClientSocket::SSLClientSocket()
21 : was_npn_negotiated_(false),
22 was_spdy_negotiated_(false),
23 protocol_negotiated_(kProtoUnknown),
24 channel_id_sent_(false),
25 signed_cert_timestamps_received_(false),
26 stapled_ocsp_response_received_(false),
27 negotiation_extension_(kExtensionUnknown) {
30 // static
31 NextProto SSLClientSocket::NextProtoFromString(
32 const std::string& proto_string) {
33 if (proto_string == "http1.1" || proto_string == "http/1.1") {
34 return kProtoHTTP11;
35 } else if (proto_string == "spdy/2") {
36 return kProtoDeprecatedSPDY2;
37 } else if (proto_string == "spdy/3") {
38 return kProtoSPDY3;
39 } else if (proto_string == "spdy/3.1") {
40 return kProtoSPDY31;
41 } else if (proto_string == "h2-14") {
42 // For internal consistency, HTTP/2 is named SPDY4 within Chromium.
43 // This is the HTTP/2 draft-14 identifier.
44 return kProtoSPDY4_14;
45 } else if (proto_string == "h2") {
46 return kProtoSPDY4;
47 } else if (proto_string == "quic/1+spdy/3") {
48 return kProtoQUIC1SPDY3;
49 } else {
50 return kProtoUnknown;
54 // static
55 const char* SSLClientSocket::NextProtoToString(NextProto next_proto) {
56 switch (next_proto) {
57 case kProtoHTTP11:
58 return "http/1.1";
59 case kProtoDeprecatedSPDY2:
60 return "spdy/2";
61 case kProtoSPDY3:
62 return "spdy/3";
63 case kProtoSPDY31:
64 return "spdy/3.1";
65 case kProtoSPDY4_14:
66 // For internal consistency, HTTP/2 is named SPDY4 within Chromium.
67 // This is the HTTP/2 draft-14 identifier.
68 return "h2-14";
69 case kProtoSPDY4:
70 return "h2";
71 case kProtoQUIC1SPDY3:
72 return "quic/1+spdy/3";
73 case kProtoUnknown:
74 break;
76 return "unknown";
79 // static
80 const char* SSLClientSocket::NextProtoStatusToString(
81 const SSLClientSocket::NextProtoStatus status) {
82 switch (status) {
83 case kNextProtoUnsupported:
84 return "unsupported";
85 case kNextProtoNegotiated:
86 return "negotiated";
87 case kNextProtoNoOverlap:
88 return "no-overlap";
90 return NULL;
93 bool SSLClientSocket::WasNpnNegotiated() const {
94 return was_npn_negotiated_;
97 NextProto SSLClientSocket::GetNegotiatedProtocol() const {
98 return protocol_negotiated_;
101 bool SSLClientSocket::IgnoreCertError(int error, int load_flags) {
102 if (error == OK)
103 return true;
104 return (load_flags & LOAD_IGNORE_ALL_CERT_ERRORS) &&
105 IsCertificateError(error);
108 bool SSLClientSocket::set_was_npn_negotiated(bool negotiated) {
109 return was_npn_negotiated_ = negotiated;
112 bool SSLClientSocket::was_spdy_negotiated() const {
113 return was_spdy_negotiated_;
116 bool SSLClientSocket::set_was_spdy_negotiated(bool negotiated) {
117 return was_spdy_negotiated_ = negotiated;
120 void SSLClientSocket::set_protocol_negotiated(NextProto protocol_negotiated) {
121 protocol_negotiated_ = protocol_negotiated;
124 void SSLClientSocket::set_negotiation_extension(
125 SSLNegotiationExtension negotiation_extension) {
126 negotiation_extension_ = negotiation_extension;
129 bool SSLClientSocket::WasChannelIDSent() const {
130 return channel_id_sent_;
133 void SSLClientSocket::set_channel_id_sent(bool channel_id_sent) {
134 channel_id_sent_ = channel_id_sent;
137 void SSLClientSocket::set_signed_cert_timestamps_received(
138 bool signed_cert_timestamps_received) {
139 signed_cert_timestamps_received_ = signed_cert_timestamps_received;
142 void SSLClientSocket::set_stapled_ocsp_response_received(
143 bool stapled_ocsp_response_received) {
144 stapled_ocsp_response_received_ = stapled_ocsp_response_received;
147 // static
148 void SSLClientSocket::RecordChannelIDSupport(
149 ChannelIDService* channel_id_service,
150 bool negotiated_channel_id,
151 bool channel_id_enabled,
152 bool supports_ecc) {
153 // Since this enum is used for a histogram, do not change or re-use values.
154 enum {
155 DISABLED = 0,
156 CLIENT_ONLY = 1,
157 CLIENT_AND_SERVER = 2,
158 CLIENT_NO_ECC = 3,
159 CLIENT_BAD_SYSTEM_TIME = 4,
160 CLIENT_NO_CHANNEL_ID_SERVICE = 5,
161 CHANNEL_ID_USAGE_MAX
162 } supported = DISABLED;
163 if (negotiated_channel_id) {
164 supported = CLIENT_AND_SERVER;
165 } else if (channel_id_enabled) {
166 if (!channel_id_service)
167 supported = CLIENT_NO_CHANNEL_ID_SERVICE;
168 else if (!supports_ecc)
169 supported = CLIENT_NO_ECC;
170 else if (!channel_id_service->IsSystemTimeValid())
171 supported = CLIENT_BAD_SYSTEM_TIME;
172 else
173 supported = CLIENT_ONLY;
175 UMA_HISTOGRAM_ENUMERATION("DomainBoundCerts.Support", supported,
176 CHANNEL_ID_USAGE_MAX);
179 // static
180 bool SSLClientSocket::IsChannelIDEnabled(
181 const SSLConfig& ssl_config,
182 ChannelIDService* channel_id_service) {
183 if (!ssl_config.channel_id_enabled)
184 return false;
185 if (!channel_id_service) {
186 DVLOG(1) << "NULL channel_id_service_, not enabling channel ID.";
187 return false;
189 if (!crypto::ECPrivateKey::IsSupported()) {
190 DVLOG(1) << "Elliptic Curve not supported, not enabling channel ID.";
191 return false;
193 if (!channel_id_service->IsSystemTimeValid()) {
194 DVLOG(1) << "System time is not within the supported range for certificate "
195 "generation, not enabling channel ID.";
196 return false;
198 return true;
201 // static
202 bool SSLClientSocket::HasCipherAdequateForHTTP2(
203 const std::vector<uint16>& cipher_suites) {
204 for (uint16 cipher : cipher_suites) {
205 if (IsSecureTLSCipherSuite(cipher))
206 return true;
208 return false;
211 // static
212 bool SSLClientSocket::IsTLSVersionAdequateForHTTP2(
213 const SSLConfig& ssl_config) {
214 return ssl_config.version_max >= SSL_PROTOCOL_VERSION_TLS1_2;
217 // static
218 std::vector<uint8_t> SSLClientSocket::SerializeNextProtos(
219 const NextProtoVector& next_protos,
220 bool can_advertise_http2) {
221 std::vector<uint8_t> wire_protos;
222 for (const NextProto next_proto : next_protos) {
223 if (!can_advertise_http2 && kProtoSPDY4MinimumVersion <= next_proto &&
224 next_proto <= kProtoSPDY4MaximumVersion) {
225 continue;
227 const std::string proto = NextProtoToString(next_proto);
228 if (proto.size() > 255) {
229 LOG(WARNING) << "Ignoring overlong NPN/ALPN protocol: " << proto;
230 continue;
232 if (proto.size() == 0) {
233 LOG(WARNING) << "Ignoring empty NPN/ALPN protocol";
234 continue;
236 wire_protos.push_back(proto.size());
237 for (const char ch : proto) {
238 wire_protos.push_back(static_cast<uint8_t>(ch));
242 return wire_protos;
245 void SSLClientSocket::RecordNegotiationExtension() {
246 if (negotiation_extension_ == kExtensionUnknown)
247 return;
248 std::string proto;
249 SSLClientSocket::NextProtoStatus status = GetNextProto(&proto);
250 if (status == kNextProtoUnsupported)
251 return;
252 // Convert protocol into numerical value for histogram.
253 NextProto protocol_negotiated = SSLClientSocket::NextProtoFromString(proto);
254 base::HistogramBase::Sample sample =
255 static_cast<base::HistogramBase::Sample>(protocol_negotiated);
256 // In addition to the protocol negotiated, we want to record which TLS
257 // extension was used, and in case of NPN, whether there was overlap between
258 // server and client list of supported protocols.
259 if (negotiation_extension_ == kExtensionNPN) {
260 if (status == kNextProtoNoOverlap) {
261 sample += 1000;
262 } else {
263 sample += 500;
265 } else {
266 DCHECK_EQ(kExtensionALPN, negotiation_extension_);
268 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSLProtocolNegotiation", sample);
271 } // namespace net