Skip to content

Commit cc85986

Browse files
Bence BékyChromium LUCI CQ
authored andcommitted
Implement ALPS in SSLClientSocketImpl and SSLServerSocketImpl.
Change-Id: I6e15414d2b591781da0103384018575e80eb81a4 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2650785 Commit-Queue: Bence Béky <bnc@chromium.org> Reviewed-by: David Benjamin <davidben@chromium.org> Cr-Commit-Position: refs/heads/master@{#851757}
1 parent 65ce2b8 commit cc85986

9 files changed

+213
-20
lines changed

net/socket/ssl_client_socket_impl.cc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <string.h>
99

1010
#include <algorithm>
11+
#include <cstring>
1112
#include <map>
1213
#include <utility>
1314

@@ -551,6 +552,18 @@ NextProto SSLClientSocketImpl::GetNegotiatedProtocol() const {
551552
return negotiated_protocol_;
552553
}
553554

555+
base::Optional<base::StringPiece>
556+
SSLClientSocketImpl::GetPeerApplicationSettings() const {
557+
if (!SSL_has_application_settings(ssl_.get())) {
558+
return base::nullopt;
559+
}
560+
561+
const uint8_t* out_data;
562+
size_t out_len;
563+
SSL_get0_peer_application_settings(ssl_.get(), &out_data, &out_len);
564+
return base::StringPiece{reinterpret_cast<const char*>(out_data), out_len};
565+
}
566+
554567
bool SSLClientSocketImpl::GetSSLInfo(SSLInfo* ssl_info) {
555568
ssl_info->Reset();
556569
if (!server_cert_)
@@ -846,6 +859,16 @@ int SSLClientSocketImpl::Init() {
846859
SSL_set_alpn_protos(ssl_.get(), wire_protos.data(), wire_protos.size());
847860
}
848861

862+
for (const auto& alps : ssl_config_.application_settings) {
863+
const char* proto_string = NextProtoToString(alps.first);
864+
const auto& data = alps.second;
865+
if (!SSL_add_application_settings(
866+
ssl_.get(), reinterpret_cast<const uint8_t*>(proto_string),
867+
strlen(proto_string), data.data(), data.size())) {
868+
return ERR_UNEXPECTED;
869+
}
870+
}
871+
849872
SSL_enable_signed_cert_timestamps(ssl_.get());
850873
SSL_enable_ocsp_stapling(ssl_.get());
851874

net/socket/ssl_client_socket_impl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "base/macros.h"
1818
#include "base/memory/ref_counted.h"
1919
#include "base/memory/weak_ptr.h"
20+
#include "base/optional.h"
2021
#include "net/base/completion_once_callback.h"
2122
#include "net/base/host_port_pair.h"
2223
#include "net/base/io_buffer.h"
@@ -85,6 +86,7 @@ class SSLClientSocketImpl : public SSLClientSocket,
8586
bool WasEverUsed() const override;
8687
bool WasAlpnNegotiated() const override;
8788
NextProto GetNegotiatedProtocol() const override;
89+
base::Optional<base::StringPiece> GetPeerApplicationSettings() const override;
8890
bool GetSSLInfo(SSLInfo* ssl_info) override;
8991
void GetConnectionAttempts(ConnectionAttempts* out) const override;
9092
void ClearConnectionAttempts() override {}

net/socket/ssl_client_socket_unittest.cc

Lines changed: 77 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,11 @@ using net::test::IsError;
101101
using net::test::IsOk;
102102

103103
using testing::_;
104-
using testing::AnyOf;
104+
using testing::Bool;
105+
using testing::Combine;
105106
using testing::Return;
106-
using testing::Truly;
107+
using testing::Values;
108+
using testing::ValuesIn;
107109

108110
namespace net {
109111

@@ -1105,13 +1107,12 @@ class SSLClientSocketReadTest
11051107
std::unique_ptr<ClientSocketFactory> wrapped_socket_factory_;
11061108
};
11071109

1108-
INSTANTIATE_TEST_SUITE_P(
1109-
All,
1110-
SSLClientSocketReadTest,
1111-
::testing::Combine(::testing::Values(READ_IF_READY_SUPPORTED,
1112-
READ_IF_READY_NOT_SUPPORTED),
1113-
::testing::Values(TEST_SSL_READ_IF_READY, TEST_SSL_READ),
1114-
::testing::ValuesIn(GetTLSVersions())));
1110+
INSTANTIATE_TEST_SUITE_P(All,
1111+
SSLClientSocketReadTest,
1112+
Combine(Values(READ_IF_READY_SUPPORTED,
1113+
READ_IF_READY_NOT_SUPPORTED),
1114+
Values(TEST_SSL_READ_IF_READY, TEST_SSL_READ),
1115+
ValuesIn(GetTLSVersions())));
11151116

11161117
// Verifies the correctness of GetSSLCertRequestInfo.
11171118
class SSLClientSocketCertRequestInfoTest : public SSLClientSocketVersionTest {
@@ -1476,7 +1477,7 @@ class HangingCertVerifier : public CertVerifier {
14761477

14771478
INSTANTIATE_TEST_SUITE_P(TLSVersion,
14781479
SSLClientSocketVersionTest,
1479-
::testing::ValuesIn(GetTLSVersions()));
1480+
ValuesIn(GetTLSVersions()));
14801481

14811482
TEST_P(SSLClientSocketVersionTest, Connect) {
14821483
ASSERT_TRUE(
@@ -2717,7 +2718,7 @@ TEST_P(SSLClientSocketVersionTest, VerifyReturnChainProperlyOrdered) {
27172718

27182719
INSTANTIATE_TEST_SUITE_P(TLSVersion,
27192720
SSLClientSocketCertRequestInfoTest,
2720-
::testing::ValuesIn(GetTLSVersions()));
2721+
ValuesIn(GetTLSVersions()));
27212722

27222723
TEST_P(SSLClientSocketCertRequestInfoTest,
27232724
DontRequestClientCertsIfServerCertInvalid) {
@@ -4046,7 +4047,7 @@ TEST_P(SSLClientSocketKeyUsageTest, RSAKeyUsageEnforcedForKnownRoot) {
40464047

40474048
INSTANTIATE_TEST_SUITE_P(RSAKeyUsageInstantiation,
40484049
SSLClientSocketKeyUsageTest,
4049-
::testing::ValuesIn(kKeyUsageTests));
4050+
ValuesIn(kKeyUsageTests));
40504051

40514052
// Test that when CT is required (in this case, by the delegate), the
40524053
// absence of CT information is a socket error.
@@ -5483,13 +5484,11 @@ class TLS13DowngradeTest
54835484
INSTANTIATE_TEST_SUITE_P(
54845485
All,
54855486
TLS13DowngradeTest,
5486-
::testing::Combine(
5487-
::testing::Values(
5488-
SpawnedTestServer::SSLOptions::TLS_MAX_VERSION_TLS1_0,
5489-
SpawnedTestServer::SSLOptions::TLS_MAX_VERSION_TLS1_1,
5490-
SpawnedTestServer::SSLOptions::TLS_MAX_VERSION_TLS1_2),
5491-
::testing::Values(false, true),
5492-
::testing::Values(false, true)));
5487+
Combine(Values(SpawnedTestServer::SSLOptions::TLS_MAX_VERSION_TLS1_0,
5488+
SpawnedTestServer::SSLOptions::TLS_MAX_VERSION_TLS1_1,
5489+
SpawnedTestServer::SSLOptions::TLS_MAX_VERSION_TLS1_2),
5490+
Bool(),
5491+
Bool()));
54935492

54945493
TEST_P(TLS13DowngradeTest, DowngradeEnforced) {
54955494
SpawnedTestServer::SSLOptions ssl_options;
@@ -5565,7 +5564,7 @@ class SSLHandshakeDetailsTest
55655564

55665565
INSTANTIATE_TEST_SUITE_P(All,
55675566
SSLHandshakeDetailsTest,
5568-
::testing::ValuesIn(kSSLHandshakeDetailsParams));
5567+
ValuesIn(kSSLHandshakeDetailsParams));
55695568

55705569
TEST_P(SSLHandshakeDetailsTest, Metrics) {
55715570
// Enable all test features in the server.
@@ -5945,4 +5944,62 @@ TEST_F(SSLClientSocketTest, VersionMinOverride) {
59455944
EXPECT_THAT(rv, IsError(ERR_SSL_VERSION_OR_CIPHER_MISMATCH));
59465945
}
59475946

5947+
class SSLClientSocketAlpsTest
5948+
: public SSLClientSocketTest,
5949+
public ::testing::WithParamInterface<std::tuple<bool, bool>> {
5950+
public:
5951+
SSLClientSocketAlpsTest()
5952+
: client_alps_enabled_(std::get<0>(GetParam())),
5953+
server_alps_enabled_(std::get<1>(GetParam())) {}
5954+
~SSLClientSocketAlpsTest() override = default;
5955+
const bool client_alps_enabled_;
5956+
const bool server_alps_enabled_;
5957+
};
5958+
5959+
INSTANTIATE_TEST_SUITE_P(All, SSLClientSocketAlpsTest, Combine(Bool(), Bool()));
5960+
5961+
TEST_P(SSLClientSocketAlpsTest, Alps) {
5962+
const std::string server_data = "server sends some test data";
5963+
const std::string client_data = "client also sends some data";
5964+
5965+
SSLServerConfig server_config;
5966+
server_config.alpn_protos = {kProtoHTTP2};
5967+
if (server_alps_enabled_) {
5968+
server_config.application_settings[kProtoHTTP2] =
5969+
std::vector<uint8_t>(server_data.begin(), server_data.end());
5970+
}
5971+
ASSERT_TRUE(
5972+
StartEmbeddedTestServer(EmbeddedTestServer::CERT_OK, server_config));
5973+
5974+
SSLConfig client_config;
5975+
client_config.alpn_protos = {kProtoHTTP2};
5976+
if (client_alps_enabled_) {
5977+
client_config.application_settings[kProtoHTTP2] =
5978+
std::vector<uint8_t>(client_data.begin(), client_data.end());
5979+
}
5980+
5981+
int rv;
5982+
ASSERT_TRUE(CreateAndConnectSSLClientSocket(client_config, &rv));
5983+
EXPECT_THAT(rv, IsOk());
5984+
5985+
SSLInfo info;
5986+
ASSERT_TRUE(sock_->GetSSLInfo(&info));
5987+
EXPECT_EQ(SSL_CONNECTION_VERSION_TLS1_3,
5988+
SSLConnectionStatusToVersion(info.connection_status));
5989+
EXPECT_EQ(SSLInfo::HANDSHAKE_FULL, info.handshake_type);
5990+
5991+
EXPECT_EQ(true, sock_->WasAlpnNegotiated());
5992+
EXPECT_EQ(kProtoHTTP2, sock_->GetNegotiatedProtocol());
5993+
5994+
// ALPS is negotiated only if ALPS is enabled both on client and server.
5995+
const auto alps_data_received_by_client = sock_->GetPeerApplicationSettings();
5996+
5997+
if (client_alps_enabled_ && server_alps_enabled_) {
5998+
ASSERT_TRUE(alps_data_received_by_client.has_value());
5999+
EXPECT_EQ(server_data, alps_data_received_by_client.value());
6000+
} else {
6001+
EXPECT_FALSE(alps_data_received_by_client.has_value());
6002+
}
6003+
}
6004+
59486005
} // namespace net

net/socket/ssl_server_socket_impl.cc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "base/lazy_instance.h"
1212
#include "base/logging.h"
1313
#include "base/memory/weak_ptr.h"
14+
#include "base/optional.h"
1415
#include "base/strings/string_util.h"
1516
#include "crypto/openssl_util.h"
1617
#include "crypto/rsa_private_key.h"
@@ -106,6 +107,7 @@ class SSLServerContextImpl::SocketImpl : public SSLServerSocket,
106107
bool WasEverUsed() const override;
107108
bool WasAlpnNegotiated() const override;
108109
NextProto GetNegotiatedProtocol() const override;
110+
base::Optional<base::StringPiece> GetPeerApplicationSettings() const override;
109111
bool GetSSLInfo(SSLInfo* ssl_info) override;
110112
void GetConnectionAttempts(ConnectionAttempts* out) const override;
111113
void ClearConnectionAttempts() override {}
@@ -347,6 +349,7 @@ void SSLServerContextImpl::SocketImpl::OnPrivateKeyComplete(
347349
DoHandshakeLoop(ERR_IO_PENDING);
348350
}
349351

352+
// static
350353
int SSLServerContextImpl::SocketImpl::ALPNSelectCallback(SSL* ssl,
351354
const uint8_t** out,
352355
uint8_t* out_len,
@@ -375,6 +378,16 @@ int SSLServerContextImpl::SocketImpl::ALPNSelectCallback(SSL* ssl,
375378
CBS_len(&client_proto)) == server_proto_str) {
376379
*out = CBS_data(&client_proto);
377380
*out_len = CBS_len(&client_proto);
381+
382+
const auto& application_settings =
383+
socket->context_->ssl_server_config_.application_settings;
384+
auto it = application_settings.find(server_proto);
385+
if (it != application_settings.end()) {
386+
const std::vector<uint8_t>& data = it->second;
387+
SSL_add_application_settings(ssl, CBS_data(&client_proto),
388+
CBS_len(&client_proto), data.data(),
389+
data.size());
390+
}
378391
return SSL_TLSEXT_ERR_OK;
379392
}
380393
}
@@ -545,6 +558,18 @@ NextProto SSLServerContextImpl::SocketImpl::GetNegotiatedProtocol() const {
545558
return negotiated_protocol_;
546559
}
547560

561+
base::Optional<base::StringPiece>
562+
SSLServerContextImpl::SocketImpl::GetPeerApplicationSettings() const {
563+
if (!SSL_has_application_settings(ssl_.get())) {
564+
return base::nullopt;
565+
}
566+
567+
const uint8_t* out_data;
568+
size_t out_len;
569+
SSL_get0_peer_application_settings(ssl_.get(), &out_data, &out_len);
570+
return base::StringPiece{reinterpret_cast<const char*>(out_data), out_len};
571+
}
572+
548573
bool SSLServerContextImpl::SocketImpl::GetSSLInfo(SSLInfo* ssl_info) {
549574
ssl_info->Reset();
550575
if (!completed_handshake_)

net/socket/ssl_server_socket_unittest.cc

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,4 +1301,69 @@ TEST_F(SSLServerSocketTest, HandshakeServerSSLPrivateKeyRequireEcdhe) {
13011301
ASSERT_THAT(server_ret, IsError(ERR_SSL_VERSION_OR_CIPHER_MISMATCH));
13021302
}
13031303

1304+
class SSLServerSocketAlpsTest
1305+
: public SSLServerSocketTest,
1306+
public ::testing::WithParamInterface<std::tuple<bool, bool>> {
1307+
public:
1308+
SSLServerSocketAlpsTest()
1309+
: client_alps_enabled_(std::get<0>(GetParam())),
1310+
server_alps_enabled_(std::get<1>(GetParam())) {}
1311+
~SSLServerSocketAlpsTest() override = default;
1312+
const bool client_alps_enabled_;
1313+
const bool server_alps_enabled_;
1314+
};
1315+
1316+
INSTANTIATE_TEST_SUITE_P(All,
1317+
SSLServerSocketAlpsTest,
1318+
::testing::Combine(::testing::Bool(),
1319+
::testing::Bool()));
1320+
1321+
TEST_P(SSLServerSocketAlpsTest, Alps) {
1322+
const std::string server_data = "server sends some test data";
1323+
const std::string client_data = "client also sends some data";
1324+
1325+
server_ssl_config_.alpn_protos = {kProtoHTTP2};
1326+
if (server_alps_enabled_) {
1327+
server_ssl_config_.application_settings[kProtoHTTP2] =
1328+
std::vector<uint8_t>(server_data.begin(), server_data.end());
1329+
}
1330+
1331+
client_ssl_config_.alpn_protos = {kProtoHTTP2};
1332+
if (client_alps_enabled_) {
1333+
client_ssl_config_.application_settings[kProtoHTTP2] =
1334+
std::vector<uint8_t>(client_data.begin(), client_data.end());
1335+
}
1336+
1337+
ASSERT_NO_FATAL_FAILURE(CreateContext());
1338+
ASSERT_NO_FATAL_FAILURE(CreateSockets());
1339+
1340+
TestCompletionCallback handshake_callback;
1341+
int server_ret = server_socket_->Handshake(handshake_callback.callback());
1342+
1343+
TestCompletionCallback connect_callback;
1344+
int client_ret = client_socket_->Connect(connect_callback.callback());
1345+
1346+
client_ret = connect_callback.GetResult(client_ret);
1347+
server_ret = handshake_callback.GetResult(server_ret);
1348+
1349+
ASSERT_THAT(client_ret, IsOk());
1350+
ASSERT_THAT(server_ret, IsOk());
1351+
1352+
// ALPS is negotiated only if ALPS is enabled both on client and server.
1353+
const auto alps_data_received_by_client =
1354+
client_socket_->GetPeerApplicationSettings();
1355+
const auto alps_data_received_by_server =
1356+
server_socket_->GetPeerApplicationSettings();
1357+
1358+
if (client_alps_enabled_ && server_alps_enabled_) {
1359+
ASSERT_TRUE(alps_data_received_by_client.has_value());
1360+
EXPECT_EQ(server_data, alps_data_received_by_client.value());
1361+
ASSERT_TRUE(alps_data_received_by_server.has_value());
1362+
EXPECT_EQ(client_data, alps_data_received_by_server.value());
1363+
} else {
1364+
EXPECT_FALSE(alps_data_received_by_client.has_value());
1365+
EXPECT_FALSE(alps_data_received_by_server.has_value());
1366+
}
1367+
}
1368+
13041369
} // namespace net

net/socket/stream_socket.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ void StreamSocket::SetBeforeConnectCallback(
1313
NOTREACHED();
1414
}
1515

16+
base::Optional<base::StringPiece> StreamSocket::GetPeerApplicationSettings()
17+
const {
18+
return base::nullopt;
19+
}
20+
1621
void StreamSocket::GetSSLCertRequestInfo(
1722
SSLCertRequestInfo* cert_request_info) const {
1823
NOTREACHED();

net/socket/stream_socket.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include "base/bind.h"
1111
#include "base/macros.h"
12+
#include "base/optional.h"
1213
#include "net/base/net_errors.h"
1314
#include "net/base/net_export.h"
1415
#include "net/dns/public/resolve_error_info.h"
@@ -136,6 +137,11 @@ class NET_EXPORT StreamSocket : public Socket {
136137
// kProtoUnknown will be returned if ALPN is not applicable.
137138
virtual NextProto GetNegotiatedProtocol() const = 0;
138139

140+
// Get data received from peer in ALPS TLS extension.
141+
// Returns a (possibly empty) value if a TLS version supporting ALPS was used
142+
// and ALPS was negotiated, nullopt otherwise.
143+
virtual base::Optional<base::StringPiece> GetPeerApplicationSettings() const;
144+
139145
// Gets the SSL connection information of the socket. Returns false if
140146
// SSL was not used by this socket.
141147
virtual bool GetSSLInfo(SSLInfo* ssl_info) = 0;

net/ssl/ssl_config.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,10 @@ struct NET_EXPORT SSLConfig {
127127
// The list of application-level protocols to enable renegotiation for.
128128
NextProtoVector renego_allowed_for_protos;
129129

130+
// ALPS TLS extension is enabled and corresponding data is sent to server
131+
// for each NextProto in |application_settings|. Data might be empty.
132+
base::flat_map<NextProto, std::vector<uint8_t>> application_settings;
133+
130134
// If the PartitionSSLSessionsByNetworkIsolationKey feature is enabled, the
131135
// session cache is partitioned by this value.
132136
NetworkIsolationKey network_isolation_key;

0 commit comments

Comments
 (0)