Delete unused downloads page asset.
[chromium-blink-merge.git] / net / socket / ssl_client_socket.cc
blobc8448b35983481f4d5b574aa331e62add4091147
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"
18 namespace net {
20 SSLClientSocket::SSLClientSocket()
21 : signed_cert_timestamps_received_(false),
22 stapled_ocsp_response_received_(false),
23 negotiation_extension_(kExtensionUnknown) {
26 // static
27 NextProto SSLClientSocket::NextProtoFromString(
28 const std::string& proto_string) {
29 if (proto_string == "http1.1" || proto_string == "http/1.1") {
30 return kProtoHTTP11;
31 } else if (proto_string == "spdy/2") {
32 return kProtoDeprecatedSPDY2;
33 } else if (proto_string == "spdy/3") {
34 return kProtoSPDY3;
35 } else if (proto_string == "spdy/3.1") {
36 return kProtoSPDY31;
37 } else if (proto_string == "h2") {
38 return kProtoHTTP2;
39 } else if (proto_string == "quic/1+spdy/3") {
40 return kProtoQUIC1SPDY3;
41 } else {
42 return kProtoUnknown;
46 // static
47 const char* SSLClientSocket::NextProtoToString(NextProto next_proto) {
48 switch (next_proto) {
49 case kProtoHTTP11:
50 return "http/1.1";
51 case kProtoDeprecatedSPDY2:
52 return "spdy/2";
53 case kProtoSPDY3:
54 return "spdy/3";
55 case kProtoSPDY31:
56 return "spdy/3.1";
57 case kProtoHTTP2:
58 return "h2";
59 case kProtoQUIC1SPDY3:
60 return "quic/1+spdy/3";
61 case kProtoUnknown:
62 break;
64 return "unknown";
67 // static
68 const char* SSLClientSocket::NextProtoStatusToString(
69 const SSLClientSocket::NextProtoStatus status) {
70 switch (status) {
71 case kNextProtoUnsupported:
72 return "unsupported";
73 case kNextProtoNegotiated:
74 return "negotiated";
75 case kNextProtoNoOverlap:
76 return "no-overlap";
78 return NULL;
81 bool SSLClientSocket::WasNpnNegotiated() const {
82 std::string unused_proto;
83 return GetNextProto(&unused_proto) == kNextProtoNegotiated;
86 NextProto SSLClientSocket::GetNegotiatedProtocol() const {
87 std::string proto;
88 if (GetNextProto(&proto) != kNextProtoNegotiated)
89 return kProtoUnknown;
90 return NextProtoFromString(proto);
93 bool SSLClientSocket::IgnoreCertError(int error, int load_flags) {
94 if (error == OK)
95 return true;
96 return (load_flags & LOAD_IGNORE_ALL_CERT_ERRORS) &&
97 IsCertificateError(error);
100 void SSLClientSocket::RecordNegotiationExtension() {
101 if (negotiation_extension_ == kExtensionUnknown)
102 return;
103 std::string proto;
104 SSLClientSocket::NextProtoStatus status = GetNextProto(&proto);
105 if (status == kNextProtoUnsupported)
106 return;
107 // Convert protocol into numerical value for histogram.
108 NextProto protocol_negotiated = SSLClientSocket::NextProtoFromString(proto);
109 base::HistogramBase::Sample sample =
110 static_cast<base::HistogramBase::Sample>(protocol_negotiated);
111 // In addition to the protocol negotiated, we want to record which TLS
112 // extension was used, and in case of NPN, whether there was overlap between
113 // server and client list of supported protocols.
114 if (negotiation_extension_ == kExtensionNPN) {
115 if (status == kNextProtoNoOverlap) {
116 sample += 1000;
117 } else {
118 sample += 500;
120 } else {
121 DCHECK_EQ(kExtensionALPN, negotiation_extension_);
123 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.SSLProtocolNegotiation", sample);
126 // static
127 void SSLClientSocket::RecordChannelIDSupport(
128 ChannelIDService* channel_id_service,
129 bool negotiated_channel_id,
130 bool channel_id_enabled,
131 bool supports_ecc) {
132 // Since this enum is used for a histogram, do not change or re-use values.
133 enum {
134 DISABLED = 0,
135 CLIENT_ONLY = 1,
136 CLIENT_AND_SERVER = 2,
137 CLIENT_NO_ECC = 3,
138 // CLIENT_BAD_SYSTEM_TIME is unused now.
139 CLIENT_BAD_SYSTEM_TIME = 4,
140 CLIENT_NO_CHANNEL_ID_SERVICE = 5,
141 CHANNEL_ID_USAGE_MAX
142 } supported = DISABLED;
143 if (negotiated_channel_id) {
144 supported = CLIENT_AND_SERVER;
145 } else if (channel_id_enabled) {
146 if (!channel_id_service)
147 supported = CLIENT_NO_CHANNEL_ID_SERVICE;
148 else if (!supports_ecc)
149 supported = CLIENT_NO_ECC;
150 else
151 supported = CLIENT_ONLY;
153 UMA_HISTOGRAM_ENUMERATION("DomainBoundCerts.Support", supported,
154 CHANNEL_ID_USAGE_MAX);
157 // static
158 bool SSLClientSocket::IsChannelIDEnabled(
159 const SSLConfig& ssl_config,
160 ChannelIDService* channel_id_service) {
161 if (!ssl_config.channel_id_enabled)
162 return false;
163 if (!channel_id_service) {
164 DVLOG(1) << "NULL channel_id_service_, not enabling channel ID.";
165 return false;
167 if (!crypto::ECPrivateKey::IsSupported()) {
168 DVLOG(1) << "Elliptic Curve not supported, not enabling channel ID.";
169 return false;
171 return true;
174 // static
175 bool SSLClientSocket::HasCipherAdequateForHTTP2(
176 const std::vector<uint16>& cipher_suites) {
177 for (uint16 cipher : cipher_suites) {
178 if (IsSecureTLSCipherSuite(cipher))
179 return true;
181 return false;
184 // static
185 bool SSLClientSocket::IsTLSVersionAdequateForHTTP2(
186 const SSLConfig& ssl_config) {
187 return ssl_config.version_max >= SSL_PROTOCOL_VERSION_TLS1_2;
190 // static
191 std::vector<uint8_t> SSLClientSocket::SerializeNextProtos(
192 const NextProtoVector& next_protos,
193 bool can_advertise_http2) {
194 std::vector<uint8_t> wire_protos;
195 for (const NextProto next_proto : next_protos) {
196 if (!can_advertise_http2 && kProtoHTTP2MinimumVersion <= next_proto &&
197 next_proto <= kProtoHTTP2MaximumVersion) {
198 continue;
200 const std::string proto = NextProtoToString(next_proto);
201 if (proto.size() > 255) {
202 LOG(WARNING) << "Ignoring overlong NPN/ALPN protocol: " << proto;
203 continue;
205 if (proto.size() == 0) {
206 LOG(WARNING) << "Ignoring empty NPN/ALPN protocol";
207 continue;
209 wire_protos.push_back(proto.size());
210 for (const char ch : proto) {
211 wire_protos.push_back(static_cast<uint8_t>(ch));
215 return wire_protos;
218 } // namespace net