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/host_port_pair.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"
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
) {
31 NextProto
SSLClientSocket::NextProtoFromString(
32 const std::string
& proto_string
) {
33 if (proto_string
== "http1.1" || proto_string
== "http/1.1") {
35 } else if (proto_string
== "spdy/2") {
36 return kProtoDeprecatedSPDY2
;
37 } else if (proto_string
== "spdy/3") {
39 } else if (proto_string
== "spdy/3.1") {
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-15") {
46 // This is the HTTP/2 draft-15 identifier.
47 return kProtoSPDY4_15
;
48 } else if (proto_string
== "quic/1+spdy/3") {
49 return kProtoQUIC1SPDY3
;
56 const char* SSLClientSocket::NextProtoToString(NextProto next_proto
) {
60 case kProtoDeprecatedSPDY2
:
67 // For internal consistency, HTTP/2 is named SPDY4 within Chromium.
68 // This is the HTTP/2 draft-14 identifier.
71 // This is the HTTP/2 draft-15 identifier.
73 case kProtoQUIC1SPDY3
:
74 return "quic/1+spdy/3";
82 const char* SSLClientSocket::NextProtoStatusToString(
83 const SSLClientSocket::NextProtoStatus status
) {
85 case kNextProtoUnsupported
:
87 case kNextProtoNegotiated
:
89 case kNextProtoNoOverlap
:
95 bool SSLClientSocket::WasNpnNegotiated() const {
96 return was_npn_negotiated_
;
99 NextProto
SSLClientSocket::GetNegotiatedProtocol() const {
100 return protocol_negotiated_
;
103 bool SSLClientSocket::IgnoreCertError(int error
, int load_flags
) {
104 if (error
== OK
|| load_flags
& LOAD_IGNORE_ALL_CERT_ERRORS
)
107 if (error
== ERR_CERT_COMMON_NAME_INVALID
&&
108 (load_flags
& LOAD_IGNORE_CERT_COMMON_NAME_INVALID
))
111 if (error
== ERR_CERT_DATE_INVALID
&&
112 (load_flags
& LOAD_IGNORE_CERT_DATE_INVALID
))
115 if (error
== ERR_CERT_AUTHORITY_INVALID
&&
116 (load_flags
& LOAD_IGNORE_CERT_AUTHORITY_INVALID
))
122 bool SSLClientSocket::set_was_npn_negotiated(bool negotiated
) {
123 return was_npn_negotiated_
= negotiated
;
126 bool SSLClientSocket::was_spdy_negotiated() const {
127 return was_spdy_negotiated_
;
130 bool SSLClientSocket::set_was_spdy_negotiated(bool negotiated
) {
131 return was_spdy_negotiated_
= negotiated
;
134 void SSLClientSocket::set_protocol_negotiated(NextProto protocol_negotiated
) {
135 protocol_negotiated_
= protocol_negotiated
;
138 void SSLClientSocket::set_negotiation_extension(
139 SSLNegotiationExtension negotiation_extension
) {
140 negotiation_extension_
= negotiation_extension
;
143 bool SSLClientSocket::WasChannelIDSent() const {
144 return channel_id_sent_
;
147 void SSLClientSocket::set_channel_id_sent(bool channel_id_sent
) {
148 channel_id_sent_
= channel_id_sent
;
151 void SSLClientSocket::set_signed_cert_timestamps_received(
152 bool signed_cert_timestamps_received
) {
153 signed_cert_timestamps_received_
= signed_cert_timestamps_received
;
156 void SSLClientSocket::set_stapled_ocsp_response_received(
157 bool stapled_ocsp_response_received
) {
158 stapled_ocsp_response_received_
= stapled_ocsp_response_received
;
162 void SSLClientSocket::RecordChannelIDSupport(
163 ChannelIDService
* channel_id_service
,
164 bool negotiated_channel_id
,
165 bool channel_id_enabled
,
167 // Since this enum is used for a histogram, do not change or re-use values.
171 CLIENT_AND_SERVER
= 2,
173 CLIENT_BAD_SYSTEM_TIME
= 4,
174 CLIENT_NO_CHANNEL_ID_SERVICE
= 5,
176 } supported
= DISABLED
;
177 if (negotiated_channel_id
) {
178 supported
= CLIENT_AND_SERVER
;
179 } else if (channel_id_enabled
) {
180 if (!channel_id_service
)
181 supported
= CLIENT_NO_CHANNEL_ID_SERVICE
;
182 else if (!supports_ecc
)
183 supported
= CLIENT_NO_ECC
;
184 else if (!channel_id_service
->IsSystemTimeValid())
185 supported
= CLIENT_BAD_SYSTEM_TIME
;
187 supported
= CLIENT_ONLY
;
189 UMA_HISTOGRAM_ENUMERATION("DomainBoundCerts.Support", supported
,
190 CHANNEL_ID_USAGE_MAX
);
194 void SSLClientSocket::RecordConnectionTypeMetrics(int ssl_version
) {
195 UpdateConnectionTypeHistograms(CONNECTION_SSL
);
196 switch (ssl_version
) {
197 case SSL_CONNECTION_VERSION_SSL2
:
198 UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL2
);
200 case SSL_CONNECTION_VERSION_SSL3
:
201 UpdateConnectionTypeHistograms(CONNECTION_SSL_SSL3
);
203 case SSL_CONNECTION_VERSION_TLS1
:
204 UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1
);
206 case SSL_CONNECTION_VERSION_TLS1_1
:
207 UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_1
);
209 case SSL_CONNECTION_VERSION_TLS1_2
:
210 UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_2
);
216 bool SSLClientSocket::IsChannelIDEnabled(
217 const SSLConfig
& ssl_config
,
218 ChannelIDService
* channel_id_service
) {
219 if (!ssl_config
.channel_id_enabled
)
221 if (!channel_id_service
) {
222 DVLOG(1) << "NULL channel_id_service_, not enabling channel ID.";
225 if (!crypto::ECPrivateKey::IsSupported()) {
226 DVLOG(1) << "Elliptic Curve not supported, not enabling channel ID.";
229 if (!channel_id_service
->IsSystemTimeValid()) {
230 DVLOG(1) << "System time is not within the supported range for certificate "
231 "generation, not enabling channel ID.";
238 bool SSLClientSocket::HasCipherAdequateForHTTP2(
239 const std::vector
<uint16
>& cipher_suites
) {
240 for (uint16 cipher
: cipher_suites
) {
241 if (IsSecureTLSCipherSuite(cipher
))
248 bool SSLClientSocket::IsTLSVersionAdequateForHTTP2(
249 const SSLConfig
& ssl_config
) {
250 return ssl_config
.version_max
>= SSL_PROTOCOL_VERSION_TLS1_2
;
254 std::vector
<uint8_t> SSLClientSocket::SerializeNextProtos(
255 const NextProtoVector
& next_protos
,
256 bool can_advertise_http2
) {
257 std::vector
<uint8_t> wire_protos
;
258 for (const NextProto next_proto
: next_protos
) {
259 if (!can_advertise_http2
&& kProtoSPDY4MinimumVersion
<= next_proto
&&
260 next_proto
<= kProtoSPDY4MaximumVersion
) {
263 const std::string proto
= NextProtoToString(next_proto
);
264 if (proto
.size() > 255) {
265 LOG(WARNING
) << "Ignoring overlong NPN/ALPN protocol: " << proto
;
268 if (proto
.size() == 0) {
269 LOG(WARNING
) << "Ignoring empty NPN/ALPN protocol";
272 wire_protos
.push_back(proto
.size());
273 for (const char ch
: proto
) {
274 wire_protos
.push_back(static_cast<uint8_t>(ch
));
281 void SSLClientSocket::RecordNegotiationExtension() {
282 if (negotiation_extension_
== kExtensionUnknown
)
285 SSLClientSocket::NextProtoStatus status
= GetNextProto(&proto
);
286 if (status
== kNextProtoUnsupported
)
288 // Convert protocol into numerical value for histogram.
289 NextProto protocol_negotiated
= SSLClientSocket::NextProtoFromString(proto
);
290 base::HistogramBase::Sample sample
=
291 static_cast<base::HistogramBase::Sample
>(protocol_negotiated
);
292 // In addition to the protocol negotiated, we want to record which TLS
293 // extension was used, and in case of NPN, whether there was overlap between
294 // server and client list of supported protocols.
295 if (negotiation_extension_
== kExtensionNPN
) {
296 if (status
== kNextProtoNoOverlap
) {
302 DCHECK_EQ(kExtensionALPN
, negotiation_extension_
);
304 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSLProtocolNegotiation", sample
);