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_macros.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"
20 SSLClientSocket::SSLClientSocket()
21 : signed_cert_timestamps_received_(false),
22 stapled_ocsp_response_received_(false),
23 negotiation_extension_(kExtensionUnknown
) {
27 NextProto
SSLClientSocket::NextProtoFromString(
28 const std::string
& proto_string
) {
29 if (proto_string
== "http1.1" || proto_string
== "http/1.1") {
31 } else if (proto_string
== "spdy/2") {
32 return kProtoDeprecatedSPDY2
;
33 } else if (proto_string
== "spdy/3") {
35 } else if (proto_string
== "spdy/3.1") {
37 } else if (proto_string
== "h2-14") {
38 // For internal consistency, HTTP/2 is named SPDY4 within Chromium.
39 // This is the HTTP/2 draft-14 identifier.
40 return kProtoHTTP2_14
;
41 } else if (proto_string
== "h2") {
43 } else if (proto_string
== "quic/1+spdy/3") {
44 return kProtoQUIC1SPDY3
;
51 const char* SSLClientSocket::NextProtoToString(NextProto next_proto
) {
55 case kProtoDeprecatedSPDY2
:
62 // For internal consistency, HTTP/2 is named SPDY4 within Chromium.
63 // This is the HTTP/2 draft-14 identifier.
67 case kProtoQUIC1SPDY3
:
68 return "quic/1+spdy/3";
76 const char* SSLClientSocket::NextProtoStatusToString(
77 const SSLClientSocket::NextProtoStatus status
) {
79 case kNextProtoUnsupported
:
81 case kNextProtoNegotiated
:
83 case kNextProtoNoOverlap
:
89 bool SSLClientSocket::WasNpnNegotiated() const {
90 std::string unused_proto
;
91 return GetNextProto(&unused_proto
) == kNextProtoNegotiated
;
94 NextProto
SSLClientSocket::GetNegotiatedProtocol() const {
96 if (GetNextProto(&proto
) != kNextProtoNegotiated
)
98 return NextProtoFromString(proto
);
101 bool SSLClientSocket::IgnoreCertError(int error
, int load_flags
) {
104 return (load_flags
& LOAD_IGNORE_ALL_CERT_ERRORS
) &&
105 IsCertificateError(error
);
108 void SSLClientSocket::RecordNegotiationExtension() {
109 if (negotiation_extension_
== kExtensionUnknown
)
112 SSLClientSocket::NextProtoStatus status
= GetNextProto(&proto
);
113 if (status
== kNextProtoUnsupported
)
115 // Convert protocol into numerical value for histogram.
116 NextProto protocol_negotiated
= SSLClientSocket::NextProtoFromString(proto
);
117 base::HistogramBase::Sample sample
=
118 static_cast<base::HistogramBase::Sample
>(protocol_negotiated
);
119 // In addition to the protocol negotiated, we want to record which TLS
120 // extension was used, and in case of NPN, whether there was overlap between
121 // server and client list of supported protocols.
122 if (negotiation_extension_
== kExtensionNPN
) {
123 if (status
== kNextProtoNoOverlap
) {
129 DCHECK_EQ(kExtensionALPN
, negotiation_extension_
);
131 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSLProtocolNegotiation", sample
);
135 void SSLClientSocket::RecordChannelIDSupport(
136 ChannelIDService
* channel_id_service
,
137 bool negotiated_channel_id
,
138 bool channel_id_enabled
,
140 // Since this enum is used for a histogram, do not change or re-use values.
144 CLIENT_AND_SERVER
= 2,
146 // CLIENT_BAD_SYSTEM_TIME is unused now.
147 CLIENT_BAD_SYSTEM_TIME
= 4,
148 CLIENT_NO_CHANNEL_ID_SERVICE
= 5,
150 } supported
= DISABLED
;
151 if (negotiated_channel_id
) {
152 supported
= CLIENT_AND_SERVER
;
153 } else if (channel_id_enabled
) {
154 if (!channel_id_service
)
155 supported
= CLIENT_NO_CHANNEL_ID_SERVICE
;
156 else if (!supports_ecc
)
157 supported
= CLIENT_NO_ECC
;
159 supported
= CLIENT_ONLY
;
161 UMA_HISTOGRAM_ENUMERATION("DomainBoundCerts.Support", supported
,
162 CHANNEL_ID_USAGE_MAX
);
166 bool SSLClientSocket::IsChannelIDEnabled(
167 const SSLConfig
& ssl_config
,
168 ChannelIDService
* channel_id_service
) {
169 if (!ssl_config
.channel_id_enabled
)
171 if (!channel_id_service
) {
172 DVLOG(1) << "NULL channel_id_service_, not enabling channel ID.";
175 if (!crypto::ECPrivateKey::IsSupported()) {
176 DVLOG(1) << "Elliptic Curve not supported, not enabling channel ID.";
183 bool SSLClientSocket::HasCipherAdequateForHTTP2(
184 const std::vector
<uint16
>& cipher_suites
) {
185 for (uint16 cipher
: cipher_suites
) {
186 if (IsSecureTLSCipherSuite(cipher
))
193 bool SSLClientSocket::IsTLSVersionAdequateForHTTP2(
194 const SSLConfig
& ssl_config
) {
195 return ssl_config
.version_max
>= SSL_PROTOCOL_VERSION_TLS1_2
;
199 std::vector
<uint8_t> SSLClientSocket::SerializeNextProtos(
200 const NextProtoVector
& next_protos
,
201 bool can_advertise_http2
) {
202 std::vector
<uint8_t> wire_protos
;
203 for (const NextProto next_proto
: next_protos
) {
204 if (!can_advertise_http2
&& kProtoHTTP2MinimumVersion
<= next_proto
&&
205 next_proto
<= kProtoHTTP2MaximumVersion
) {
208 const std::string proto
= NextProtoToString(next_proto
);
209 if (proto
.size() > 255) {
210 LOG(WARNING
) << "Ignoring overlong NPN/ALPN protocol: " << proto
;
213 if (proto
.size() == 0) {
214 LOG(WARNING
) << "Ignoring empty NPN/ALPN protocol";
217 wire_protos
.push_back(proto
.size());
218 for (const char ch
: proto
) {
219 wire_protos
.push_back(static_cast<uint8_t>(ch
));