Commit 875149a9 authored by Martin Thomson's avatar Martin Thomson

Bug 1418862 - Make HelloRetryRequest look like ServerHello, r=ekr

Update TLS 1.3 implementation for draft-22.

This makes the changes from Bug 1411475 the default mode of operation.  A new
option, SSL_ENABLE_TLS13_COMPAT_MODE, is added to control whether a client
attempts to force the server into compatibility mode.  When enabled, clients
will send a fake session_id in the ClientHello and send a ChangeCipherSpec
message before sending any encrypted records.

This patch also includes changes to make a HelloRetryRequest look like a
ServerHello.

This includes the version number change to draft-22.

--HG--
branch : NSS_TLS13_DRAFT19_BRANCH
extra : rebase_source : 0a2868314e7fed0930be029352a0824ec1eb4b46
extra : amend_source : 8a39378587292bd9acaed5de1da105806f3d0522
extra : histedit_source : b2a5f8f4439eba4c41347fea267af6a320c16e52%2C2b1453083a95b9dcfa95f54e70a197f3d870d885
parent 8561929d
......@@ -15,7 +15,6 @@ CPPSRCS = \
bloomfilter_unittest.cc \
ssl_0rtt_unittest.cc \
ssl_agent_unittest.cc \
ssl_alths_unittest.cc \
ssl_auth_unittest.cc \
ssl_cert_ext_unittest.cc \
ssl_ciphersuite_unittest.cc \
......@@ -40,6 +39,7 @@ CPPSRCS = \
ssl_renegotiation_unittest.cc \
ssl_skip_unittest.cc \
ssl_staticrsa_unittest.cc \
ssl_tls13compat_unittest.cc \
ssl_v2_client_hello_unittest.cc \
ssl_version_unittest.cc \
ssl_versionpolicy_unittest.cc \
......
......@@ -44,13 +44,14 @@ const static uint8_t kCannedTls13ClientHello[] = {
0x02, 0x05, 0x02, 0x06, 0x02, 0x02, 0x02};
const static uint8_t kCannedTls13ServerHello[] = {
0x7f, kD13, 0x9c, 0xbc, 0x14, 0x9b, 0x0e, 0x2e, 0xfa, 0x0d, 0xf3, 0xf0,
0x5c, 0x70, 0x7a, 0xe0, 0xd1, 0x9b, 0x3e, 0x5a, 0x44, 0x6b, 0xdf, 0xe5,
0xc2, 0x28, 0x64, 0xf7, 0x00, 0xc1, 0x9c, 0x08, 0x76, 0x08, 0x13, 0x01,
0x00, 0x28, 0x00, 0x28, 0x00, 0x24, 0x00, 0x1d, 0x00, 0x20, 0xc2, 0xcf,
0x23, 0x17, 0x64, 0x23, 0x03, 0xf0, 0xfb, 0x45, 0x98, 0x26, 0xd1, 0x65,
0x24, 0xa1, 0x6c, 0xa9, 0x80, 0x8f, 0x2c, 0xac, 0x0a, 0xea, 0x53, 0x3a,
0xcb, 0xe3, 0x08, 0x84, 0xae, 0x19};
0x03, 0x03, 0x9c, 0xbc, 0x14, 0x9b, 0x0e, 0x2e, 0xfa, 0x0d, 0xf3,
0xf0, 0x5c, 0x70, 0x7a, 0xe0, 0xd1, 0x9b, 0x3e, 0x5a, 0x44, 0x6b,
0xdf, 0xe5, 0xc2, 0x28, 0x64, 0xf7, 0x00, 0xc1, 0x9c, 0x08, 0x76,
0x08, 0x00, 0x13, 0x01, 0x00, 0x00, 0x2e, 0x00, 0x28, 0x00, 0x24,
0x00, 0x1d, 0x00, 0x20, 0xc2, 0xcf, 0x23, 0x17, 0x64, 0x23, 0x03,
0xf0, 0xfb, 0x45, 0x98, 0x26, 0xd1, 0x65, 0x24, 0xa1, 0x6c, 0xa9,
0x80, 0x8f, 0x2c, 0xac, 0x0a, 0xea, 0x53, 0x3a, 0xcb, 0xe3, 0x08,
0x84, 0xae, 0x19, 0x00, 0x2b, 0x00, 0x02, 0x7f, kD13};
static const char *k0RttData = "ABCDEF";
TEST_P(TlsAgentTest, EarlyFinished) {
......
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <memory>
#include <vector>
#include "ssl.h"
#include "sslerr.h"
#include "sslproto.h"
#include "gtest_utils.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
namespace nss_test {
static const uint32_t kServerHelloVersionAlt = SSL_LIBRARY_VERSION_TLS_1_2;
static const uint16_t kServerHelloVersionRegular =
0x7f00 | TLS_1_3_DRAFT_VERSION;
class AltHandshakeTest : public TlsConnectStreamTls13 {
protected:
void SetUp() {
TlsConnectStreamTls13::SetUp();
client_ccs_recorder_ =
std::make_shared<TlsRecordRecorder>(kTlsChangeCipherSpecType);
server_handshake_recorder_ =
std::make_shared<TlsRecordRecorder>(kTlsHandshakeType);
server_ccs_recorder_ =
std::make_shared<TlsRecordRecorder>(kTlsChangeCipherSpecType);
server_hello_recorder_ =
std::make_shared<TlsInspectorRecordHandshakeMessage>(
kTlsHandshakeServerHello);
}
void SetAltHandshakeTypeEnabled() {
client_->SetAltHandshakeTypeEnabled();
server_->SetAltHandshakeTypeEnabled();
}
void InstallFilters() {
client_->SetPacketFilter(client_ccs_recorder_);
auto chain = std::make_shared<ChainedPacketFilter>(ChainedPacketFilterInit(
{server_handshake_recorder_, server_ccs_recorder_,
server_hello_recorder_}));
server_->SetPacketFilter(chain);
}
void CheckServerHelloRecordVersion(uint16_t record_version) {
ASSERT_EQ(record_version,
server_handshake_recorder_->record(0).header.version());
}
void CheckServerHelloVersion(uint16_t server_hello_version) {
uint32_t ver;
ASSERT_TRUE(server_hello_recorder_->buffer().Read(0, 2, &ver));
ASSERT_EQ(server_hello_version, ver);
}
void CheckForRegularHandshake() {
EXPECT_EQ(0U, client_ccs_recorder_->count());
EXPECT_EQ(0U, server_ccs_recorder_->count());
CheckServerHelloVersion(kServerHelloVersionRegular);
CheckServerHelloRecordVersion(SSL_LIBRARY_VERSION_TLS_1_0);
}
void CheckForAltHandshake() {
EXPECT_EQ(1U, client_ccs_recorder_->count());
EXPECT_EQ(1U, server_ccs_recorder_->count());
CheckServerHelloVersion(kServerHelloVersionAlt);
CheckServerHelloRecordVersion(SSL_LIBRARY_VERSION_TLS_1_2);
}
std::shared_ptr<TlsRecordRecorder> client_ccs_recorder_;
std::shared_ptr<TlsRecordRecorder> server_handshake_recorder_;
std::shared_ptr<TlsRecordRecorder> server_ccs_recorder_;
std::shared_ptr<TlsInspectorRecordHandshakeMessage> server_hello_recorder_;
};
TEST_F(AltHandshakeTest, ClientOnly) {
client_->SetAltHandshakeTypeEnabled();
InstallFilters();
Connect();
CheckForRegularHandshake();
}
TEST_F(AltHandshakeTest, ServerOnly) {
server_->SetAltHandshakeTypeEnabled();
InstallFilters();
Connect();
CheckForRegularHandshake();
}
TEST_F(AltHandshakeTest, Enabled) {
SetAltHandshakeTypeEnabled();
InstallFilters();
Connect();
CheckForAltHandshake();
}
TEST_F(AltHandshakeTest, ZeroRtt) {
SetAltHandshakeTypeEnabled();
SetupForZeroRtt();
SetAltHandshakeTypeEnabled();
client_->Set0RttEnabled(true);
server_->Set0RttEnabled(true);
InstallFilters();
ExpectResumption(RESUME_TICKET);
ZeroRttSendReceive(true, true);
Handshake();
ExpectEarlyDataAccepted(true);
CheckConnected();
CheckForAltHandshake();
}
// Neither client nor server has the extension prior to resumption, so the
// client doesn't send a CCS before its 0-RTT data.
TEST_F(AltHandshakeTest, DisabledBeforeZeroRtt) {
SetupForZeroRtt();
SetAltHandshakeTypeEnabled();
client_->Set0RttEnabled(true);
server_->Set0RttEnabled(true);
InstallFilters();
ExpectResumption(RESUME_TICKET);
ZeroRttSendReceive(true, true);
Handshake();
ExpectEarlyDataAccepted(true);
CheckConnected();
EXPECT_EQ(0U, client_ccs_recorder_->count());
EXPECT_EQ(1U, server_ccs_recorder_->count());
CheckServerHelloVersion(kServerHelloVersionAlt);
}
// Both use the alternative in the initial handshake but only the server enables
// it on resumption.
TEST_F(AltHandshakeTest, ClientDisabledAfterZeroRtt) {
SetAltHandshakeTypeEnabled();
SetupForZeroRtt();
server_->SetAltHandshakeTypeEnabled();
client_->Set0RttEnabled(true);
server_->Set0RttEnabled(true);
InstallFilters();
ExpectResumption(RESUME_TICKET);
ZeroRttSendReceive(true, true);
Handshake();
ExpectEarlyDataAccepted(true);
CheckConnected();
CheckForRegularHandshake();
}
// If the alternative handshake isn't negotiated after 0-RTT, and the client has
// it enabled, it will send a ChangeCipherSpec. The server chokes on it if it
// hasn't negotiated the alternative handshake.
TEST_F(AltHandshakeTest, ServerDisabledAfterZeroRtt) {
SetAltHandshakeTypeEnabled();
SetupForZeroRtt();
client_->SetAltHandshakeTypeEnabled();
client_->Set0RttEnabled(true);
server_->Set0RttEnabled(true);
client_->Handshake(); // Send ClientHello (and CCS)
server_->Handshake(); // Consume the ClientHello, which is OK.
client_->ExpectResumption();
client_->Handshake(); // Read the server handshake.
EXPECT_EQ(TlsAgent::STATE_CONNECTED, client_->state());
// Now the server reads the CCS instead of more handshake messages.
ExpectAlert(server_, kTlsAlertBadRecordMac);
server_->Handshake();
EXPECT_EQ(TlsAgent::STATE_ERROR, server_->state());
client_->Handshake(); // Consume the alert.
EXPECT_EQ(TlsAgent::STATE_ERROR, client_->state());
}
} // nss_test
......@@ -159,13 +159,11 @@ TEST_P(TlsConnectTls12, ClientAuthBigRsaCheckSigAlg) {
class TlsZeroCertificateRequestSigAlgsFilter : public TlsHandshakeFilter {
public:
TlsZeroCertificateRequestSigAlgsFilter()
: TlsHandshakeFilter({kTlsHandshakeCertificateRequest}) {}
virtual PacketFilter::Action FilterHandshake(
const TlsHandshakeFilter::HandshakeHeader& header,
const DataBuffer& input, DataBuffer* output) {
if (header.handshake_type() != kTlsHandshakeCertificateRequest) {
return KEEP;
}
TlsParser parser(input);
std::cerr << "Zeroing CertReq.supported_signature_algorithms" << std::endl;
......
......@@ -103,14 +103,11 @@ TEST_P(TlsConnectGenericPre13, ConnectFfdheServer) {
class TlsDheServerKeyExchangeDamager : public TlsHandshakeFilter {
public:
TlsDheServerKeyExchangeDamager() {}
TlsDheServerKeyExchangeDamager()
: TlsHandshakeFilter({kTlsHandshakeServerKeyExchange}) {}
virtual PacketFilter::Action FilterHandshake(
const TlsHandshakeFilter::HandshakeHeader& header,
const DataBuffer& input, DataBuffer* output) {
if (header.handshake_type() != kTlsHandshakeServerKeyExchange) {
return KEEP;
}
// Damage the first octet of dh_p. Anything other than the known prime will
// be rejected as "weak" when we have SSL_REQUIRE_DH_NAMED_GROUPS enabled.
*output = input;
......@@ -144,7 +141,8 @@ class TlsDheSkeChangeY : public TlsHandshakeFilter {
kYZeroPad
};
TlsDheSkeChangeY(ChangeYTo change) : change_Y_(change) {}
TlsDheSkeChangeY(uint8_t handshake_type, ChangeYTo change)
: TlsHandshakeFilter({handshake_type}), change_Y_(change) {}
protected:
void ChangeY(const DataBuffer& input, DataBuffer* output, size_t offset,
......@@ -210,7 +208,9 @@ class TlsDheSkeChangeY : public TlsHandshakeFilter {
class TlsDheSkeChangeYServer : public TlsDheSkeChangeY {
public:
TlsDheSkeChangeYServer(ChangeYTo change, bool modify)
: TlsDheSkeChangeY(change), modify_(modify), p_() {}
: TlsDheSkeChangeY(kTlsHandshakeServerKeyExchange, change),
modify_(modify),
p_() {}
const DataBuffer& prime() const { return p_; }
......@@ -218,10 +218,6 @@ class TlsDheSkeChangeYServer : public TlsDheSkeChangeY {
virtual PacketFilter::Action FilterHandshake(
const TlsHandshakeFilter::HandshakeHeader& header,
const DataBuffer& input, DataBuffer* output) override {
if (header.handshake_type() != kTlsHandshakeServerKeyExchange) {
return KEEP;
}
size_t offset = 2;
// Read dh_p
uint32_t dh_len = 0;
......@@ -251,16 +247,13 @@ class TlsDheSkeChangeYClient : public TlsDheSkeChangeY {
TlsDheSkeChangeYClient(
ChangeYTo change,
std::shared_ptr<const TlsDheSkeChangeYServer> server_filter)
: TlsDheSkeChangeY(change), server_filter_(server_filter) {}
: TlsDheSkeChangeY(kTlsHandshakeClientKeyExchange, change),
server_filter_(server_filter) {}
protected:
virtual PacketFilter::Action FilterHandshake(
const TlsHandshakeFilter::HandshakeHeader& header,
const DataBuffer& input, DataBuffer* output) override {
if (header.handshake_type() != kTlsHandshakeClientKeyExchange) {
return KEEP;
}
ChangeY(input, output, 0, server_filter_->prime());
return CHANGE;
}
......@@ -365,13 +358,10 @@ INSTANTIATE_TEST_CASE_P(
class TlsDheSkeMakePEven : public TlsHandshakeFilter {
public:
TlsDheSkeMakePEven() : TlsHandshakeFilter({kTlsHandshakeServerKeyExchange}) {}
virtual PacketFilter::Action FilterHandshake(
const TlsHandshakeFilter::HandshakeHeader& header,
const DataBuffer& input, DataBuffer* output) {
if (header.handshake_type() != kTlsHandshakeServerKeyExchange) {
return KEEP;
}
// Find the end of dh_p
uint32_t dh_len = 0;
EXPECT_TRUE(input.Read(0, 2, &dh_len));
......@@ -399,13 +389,10 @@ TEST_P(TlsConnectGenericPre13, MakeDhePEven) {
class TlsDheSkeZeroPadP : public TlsHandshakeFilter {
public:
TlsDheSkeZeroPadP() : TlsHandshakeFilter({kTlsHandshakeServerKeyExchange}) {}
virtual PacketFilter::Action FilterHandshake(
const TlsHandshakeFilter::HandshakeHeader& header,
const DataBuffer& input, DataBuffer* output) {
if (header.handshake_type() != kTlsHandshakeServerKeyExchange) {
return KEEP;
}
*output = input;
uint32_t dh_len = 0;
EXPECT_TRUE(input.Read(0, 2, &dh_len));
......@@ -559,16 +546,15 @@ TEST_P(TlsConnectTls13, ResumeFfdhe) {
class TlsDheSkeChangeSignature : public TlsHandshakeFilter {
public:
TlsDheSkeChangeSignature(uint16_t version, const uint8_t* data, size_t len)
: version_(version), data_(data), len_(len) {}
: TlsHandshakeFilter({kTlsHandshakeServerKeyExchange}),
version_(version),
data_(data),
len_(len) {}
protected:
virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header,
const DataBuffer& input,
DataBuffer* output) {
if (header.handshake_type() != kTlsHandshakeServerKeyExchange) {
return KEEP;
}
TlsParser parser(input);
EXPECT_TRUE(parser.SkipVariable(2)); // dh_p
EXPECT_TRUE(parser.SkipVariable(2)); // dh_g
......
......@@ -105,7 +105,7 @@ class TlsDropDatagram13 : public TlsConnectDatagram13 {
server_->ssl_fd(), 1,
[](PRFileDesc* fd, SSLHandshakeType message, PRUint8* data,
unsigned int* len, unsigned int maxLen, void* arg) -> PRBool {
SSLInt_SetMTU(fd, 400); // Splits the certificate.
SSLInt_SetMTU(fd, 500); // Splits the certificate.
return PR_FALSE;
},
nullptr,
......@@ -654,9 +654,9 @@ TEST_F(TlsDropDatagram13, SendOutOfOrderAppWithHandshakeKey) {
auto spec = capturer.spec(0);
ASSERT_NE(nullptr, spec.get());
ASSERT_EQ(2, spec->epoch());
ASSERT_TRUE(client_->SendEncryptedRecord(spec, 0xfeff, 0x0002000000000002,
kTlsApplicationDataType,
DataBuffer(buf, sizeof(buf))));
ASSERT_TRUE(client_->SendEncryptedRecord(
spec, SSL_LIBRARY_VERSION_DTLS_1_2_WIRE, 0x0002000000000002,
kTlsApplicationDataType, DataBuffer(buf, sizeof(buf))));
// Now have the server consume the bogus message.
server_->ExpectSendAlert(illegal_parameter, kTlsAlertFatal);
......@@ -680,9 +680,9 @@ TEST_F(TlsDropDatagram13, SendOutOfOrderHsNonsenseWithHandshakeKey) {
auto spec = capturer.spec(0);
ASSERT_NE(nullptr, spec.get());
ASSERT_EQ(2, spec->epoch());
ASSERT_TRUE(client_->SendEncryptedRecord(spec, 0xfeff, 0x0002000000000002,
kTlsHandshakeType,
DataBuffer(buf, sizeof(buf))));
ASSERT_TRUE(client_->SendEncryptedRecord(
spec, SSL_LIBRARY_VERSION_DTLS_1_2_WIRE, 0x0002000000000002,
kTlsHandshakeType, DataBuffer(buf, sizeof(buf))));
server_->Handshake();
EXPECT_EQ(2UL, server_filters_.ack_->count());
CheckAcks(server_filters_, 0, {0x0002000000000000ULL});
......
......@@ -193,7 +193,9 @@ TEST_P(TlsConnectGenericPre13, P384PriorityFromModelSocket) {
class TlsKeyExchangeGroupCapture : public TlsHandshakeFilter {
public:
TlsKeyExchangeGroupCapture() : group_(ssl_grp_none) {}
TlsKeyExchangeGroupCapture()
: TlsHandshakeFilter({kTlsHandshakeServerKeyExchange}),
group_(ssl_grp_none) {}
SSLNamedGroup group() const { return group_; }
......@@ -201,10 +203,6 @@ class TlsKeyExchangeGroupCapture : public TlsHandshakeFilter {
virtual PacketFilter::Action FilterHandshake(const HandshakeHeader &header,
const DataBuffer &input,
DataBuffer *output) {
if (header.handshake_type() != kTlsHandshakeServerKeyExchange) {
return KEEP;
}
uint32_t value = 0;
EXPECT_TRUE(input.Read(0, 1, &value));
EXPECT_EQ(3U, value) << "curve type has to be 3";
......@@ -518,16 +516,12 @@ TEST_P(TlsKeyExchangeTest13, MultipleClientShares) {
// Replace the point in the client key exchange message with an empty one
class ECCClientKEXFilter : public TlsHandshakeFilter {
public:
ECCClientKEXFilter() {}
ECCClientKEXFilter() : TlsHandshakeFilter({kTlsHandshakeClientKeyExchange}) {}
protected:
virtual PacketFilter::Action FilterHandshake(const HandshakeHeader &header,
const DataBuffer &input,
DataBuffer *output) {
if (header.handshake_type() != kTlsHandshakeClientKeyExchange) {
return KEEP;
}
// Replace the client key exchange message with an empty point
output->Allocate(1);
output->Write(0, 0U, 1); // set point length 0
......@@ -538,16 +532,12 @@ class ECCClientKEXFilter : public TlsHandshakeFilter {
// Replace the point in the server key exchange message with an empty one
class ECCServerKEXFilter : public TlsHandshakeFilter {
public:
ECCServerKEXFilter() {}
ECCServerKEXFilter() : TlsHandshakeFilter({kTlsHandshakeServerKeyExchange}) {}
protected:
virtual PacketFilter::Action FilterHandshake(const HandshakeHeader &header,
const DataBuffer &input,
DataBuffer *output) {
if (header.handshake_type() != kTlsHandshakeServerKeyExchange) {
return KEEP;
}
// Replace the server key exchange message with an empty point
output->Allocate(4);
output->Write(0, 3U, 1); // named curve
......
......@@ -64,15 +64,11 @@ class TlsExtensionDamager : public TlsExtensionFilter {
class TlsExtensionAppender : public TlsHandshakeFilter {
public:
TlsExtensionAppender(uint8_t handshake_type, uint16_t ext, DataBuffer& data)
: handshake_type_(handshake_type), extension_(ext), data_(data) {}
: TlsHandshakeFilter({handshake_type}), extension_(ext), data_(data) {}
virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header,
const DataBuffer& input,
DataBuffer* output) {
if (header.handshake_type() != handshake_type_) {
return KEEP;
}
TlsParser parser(input);
if (!TlsExtensionFilter::FindExtensions(&parser, header)) {
return KEEP;
......@@ -117,7 +113,6 @@ class TlsExtensionAppender : public TlsHandshakeFilter {
return true;
}
const uint8_t handshake_type_;
const uint16_t extension_;
const DataBuffer data_;
};
......@@ -1054,13 +1049,6 @@ TEST_P(TlsBogusExtensionTest13, AddVersionExtensionCertificateRequest) {
Run(kTlsHandshakeCertificateRequest, ssl_tls13_supported_versions_xtn);
}
TEST_P(TlsBogusExtensionTest13, AddVersionExtensionHelloRetryRequest) {
static const std::vector<SSLNamedGroup> groups = {ssl_grp_ec_secp384r1};
server_->ConfigNamedGroups(groups);
Run(kTlsHandshakeHelloRetryRequest, ssl_tls13_supported_versions_xtn);
}
// NewSessionTicket allows unknown extensions AND it isn't protected by the
// Finished. So adding an unknown extension doesn't cause an error.
TEST_P(TlsBogusExtensionTest13, AddBogusExtensionNewSessionTicket) {
......
......@@ -16,7 +16,6 @@
'selfencrypt_unittest.cc',
'ssl_0rtt_unittest.cc',
'ssl_agent_unittest.cc',
'ssl_alths_unittest.cc',
'ssl_auth_unittest.cc',
'ssl_cert_ext_unittest.cc',
'ssl_ciphersuite_unittest.cc',
......@@ -41,6 +40,7 @@
'ssl_renegotiation_unittest.cc',
'ssl_skip_unittest.cc',
'ssl_staticrsa_unittest.cc',
'ssl_tls13compat_unittest.cc',
'ssl_v2_client_hello_unittest.cc',
'ssl_version_unittest.cc',
'ssl_versionpolicy_unittest.cc',
......
......@@ -559,17 +559,6 @@ TEST_F(TlsConnectStreamTls13, RetryCallbackWithSessionTicketToken) {
EXPECT_TRUE(cb_run);
}
std::shared_ptr<TlsAgent> MakeNewServer(std::shared_ptr<TlsAgent>& client) {
auto server = std::make_shared<TlsAgent>(TlsAgent::kServerRsa,
TlsAgent::SERVER, client->variant());
server->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
SSL_LIBRARY_VERSION_TLS_1_3);
client->SetPeer(server);
server->SetPeer(client);
server->StartConnect();
return server;
}
void TriggerHelloRetryRequest(std::shared_ptr<TlsAgent>& client,
std::shared_ptr<TlsAgent>& server) {
size_t cb_called = 0;
......@@ -589,7 +578,7 @@ TEST_P(TlsConnectTls13, RetryStateless) {
EnsureTlsSetup();
TriggerHelloRetryRequest(client_, server_);
server_ = MakeNewServer(client_);
MakeNewServer();
Handshake();
SendReceive();
......@@ -618,7 +607,7 @@ TEST_F(TlsConnectStreamTls13, RetryStatelessDamageFirstClientHello) {
client_->SetPacketFilter(damage_ch);
TriggerHelloRetryRequest(client_, server_);
server_ = MakeNewServer(client_);
MakeNewServer();
// Key exchange fails when the handshake continues because client and server
// disagree about the transcript.
......@@ -634,7 +623,7 @@ TEST_F(TlsConnectStreamTls13, RetryStatelessDamageSecondClientHello) {
EnsureTlsSetup();
TriggerHelloRetryRequest(client_, server_);
server_ = MakeNewServer(client_);
MakeNewServer();
auto damage_ch = std::make_shared<TlsExtensionInjector>(0xfff3, DataBuffer());
client_->SetPacketFilter(damage_ch);
......@@ -648,6 +637,22 @@ TEST_F(TlsConnectStreamTls13, RetryStatelessDamageSecondClientHello) {
client_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
}
// Read the cipher suite from the HRR and disable it on the identified agent.
static void DisableSuiteFromHrr(
std::shared_ptr<TlsAgent>& agent,
std::shared_ptr<TlsInspectorRecordHandshakeMessage>& capture_hrr) {
uint32_t tmp;
size_t offset = 2 + 32; // skip version + server_random
ASSERT_TRUE(
capture_hrr->buffer().Read(offset, 1, &tmp)); // session_id length
EXPECT_EQ(0U, tmp);
offset += 1 + tmp;
ASSERT_TRUE(capture_hrr->buffer().Read(offset, 2, &tmp)); // suite
EXPECT_EQ(
SECSuccess,
SSL_CipherPrefSet(agent->ssl_fd(), static_cast<uint16_t>(tmp), PR_FALSE));
}
TEST_P(TlsConnectTls13, RetryStatelessDisableSuiteClient) {
ConfigureSelfEncrypt();
EnsureTlsSetup();
......@@ -657,20 +662,15 @@ TEST_P(TlsConnectTls13, RetryStatelessDisableSuiteClient) {
server_->SetPacketFilter(capture_hrr);
TriggerHelloRetryRequest(client_, server_);
server_ = MakeNewServer(client_);
MakeNewServer();
// Read the cipher suite from the HRR and disable it on the client.
uint32_t suite;
ASSERT_TRUE(capture_hrr->buffer().Read(2, 2, &suite));
EXPECT_EQ(SECSuccess,
SSL_CipherPrefSet(client_->ssl_fd(), static_cast<uint16_t>(suite),
PR_FALSE));
DisableSuiteFromHrr(client_, capture_hrr);
// The client thinks that the HelloRetryRequest is bad, even though its
// because it changed its mind about the cipher suite.
ExpectAlert(client_, kTlsAlertIllegalParameter);
Handshake();
client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_HELLO_RETRY_REQUEST);
client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
}
......@@ -683,14 +683,9 @@ TEST_P(TlsConnectTls13, RetryStatelessDisableSuiteServer) {
server_->SetPacketFilter(capture_hrr);
TriggerHelloRetryRequest(client_, server_);
server_ = MakeNewServer(client_);
MakeNewServer();
// Read the cipher suite from the HRR and disable it on the server.
uint32_t suite;
ASSERT_TRUE(capture_hrr->buffer().Read(2, 2, &suite));
EXPECT_EQ(SECSuccess,
SSL_CipherPrefSet(server_->ssl_fd(), static_cast<uint16_t>(suite),
PR_FALSE));
DisableSuiteFromHrr(server_, capture_hrr);
ExpectAlert(server_, kTlsAlertIllegalParameter);
Handshake();
......@@ -703,7 +698,7 @@ TEST_P(TlsConnectTls13, RetryStatelessDisableGroupClient) {
EnsureTlsSetup();
TriggerHelloRetryRequest(client_, server_);
server_ = MakeNewServer(client_);
MakeNewServer();
static const std::vector<SSLNamedGroup> groups = {ssl_grp_ec_secp384r1};
client_->ConfigNamedGroups(groups);
......@@ -723,7 +718,7 @@ TEST_P(TlsConnectTls13, RetryStatelessDisableGroupServer) {
EnsureTlsSetup();
TriggerHelloRetryRequest(client_, server_);
server_ = MakeNewServer(client_);
MakeNewServer();
static const std::vector<SSLNamedGroup> groups = {ssl_grp_ec_secp384r1};
server_->ConfigNamedGroups(groups);
......@@ -751,7 +746,7 @@ TEST_P(TlsConnectTls13, RetryStatelessBadCookie) {
ASSERT_NE(nullptr, hmac_key);
SSLInt_SetSelfEncryptMacKey(hmac_key); // Passes ownership.
server_ = MakeNewServer(client_);
MakeNewServer();
ExpectAlert(server_, kTlsAlertIllegalParameter);
Handshake();
......@@ -912,16 +907,30 @@ class HelloRetryRequestAgentTest : public TlsAgentTestClient {
void MakeCannedHrr(const uint8_t* body, size_t len, DataBuffer* hrr_record,
uint32_t seq_num = 0) const {
DataBuffer hrr_data;
const uint8_t ssl_hello_retry_random[] = {
0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, 0xBE, 0x1D, 0x8C,
0x02, 0x1E, 0x65, 0xB8, 0x91, 0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB,
0x8C, 0x5E, 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C};
hrr_data.Allocate(len + 6);
size_t i = 0;
i = hrr_data.Write(i, 0x7f00 | TLS_1_3_DRAFT_VERSION, 2);
i = hrr_data.Write(i, 0x0303, 2);
i = hrr_data.Write(i, ssl_hello_retry_random,
sizeof(ssl_hello_retry_random));
i = hrr_data.Write(i, static_cast<uint32_t>(0), 1); // session_id
i = hrr_data.Write(i, TLS_AES_128_GCM_SHA256, 2);
i = hrr_data.Write(i, static_cast<uint32_t>(len), 2);
i = hrr_data.Write(i, ssl_compression_null, 1);
// Add extensions. First a length, which includes the supported version.
i = hrr_data.Write(i, static_cast<uint32_t>(len) + 6, 2);
// Now the supported version.
i = hrr_data.Write(i, ssl_tls13_supported_versions_xtn, 2);
i = hrr_data.Write(i, 2, 2);
i = hrr_data.Write(i, 0x7f00 | TLS_1_3_DRAFT_VERSION, 2);
if (len) {
hrr_data.Write(i, body, len);
}
DataBuffer hrr;
MakeHandshakeMessage(kTlsHandshakeHelloRetryRequest, hrr_data.data(),
MakeHandshakeMessage(kTlsHandshakeServerHello, hrr_data.data(),
hrr_data.len(), &hrr, seq_num);
MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3, hrr.data(),
hrr.len(), hrr_record, seq_num);
......
......@@ -85,13 +85,13 @@ class TlsAlertRecorder : public TlsRecordFilter {
};
class HelloTruncator : public TlsHandshakeFilter {
public:
HelloTruncator()
: TlsHandshakeFilter(
{kTlsHandshakeClientHello, kTlsHandshakeServerHello}) {}
PacketFilter::Action FilterHandshake(const HandshakeHeader& header,
const DataBuffer& input,
DataBuffer* output) override {
if (header.handshake_type() != kTlsHandshakeClientHello &&
header.handshake_type() != kTlsHandshakeServerHello) {
return KEEP;
}
output->Assign(input.data(), input.len() - 1);
return CHANGE;
}
......
......@@ -490,16 +490,13 @@ TEST_P(TlsConnectStream, TestResumptionOverrideCipher) {
class SelectedVersionReplacer : public TlsHandshakeFilter {
public:
SelectedVersionReplacer(uint16_t version) : version_(version) {}
SelectedVersionReplacer(uint16_t version)
: TlsHandshakeFilter({kTlsHandshakeServerHello}), version_(version) {}
protected:
PacketFilter::Action FilterHandshake(const HandshakeHeader& header,
const DataBuffer& input,
DataBuffer* output) override {
if (header.handshake_type() != kTlsHandshakeServerHello) {
return KEEP;
}