Commit 0f52cc48 authored by Martin Thomson's avatar Martin Thomson

Bug 1411475 - Set the record layer version, r=ekr

This refactors the code so that the cipher specs have a field that includes the
record layer version number.  This is used to cap the ClientHello record
version, as well as set the 1.0/1.2 version as necessary for the two TLS 1.3
versions.

--HG--
branch : NSS_TLS13_DRAFT19_BRANCH
extra : rebase_source : 3b33a6c25c037d23e14270a4e8bf7da2d7f7d0a6
extra : amend_source : 19d43f91a6cd33d4baa16ad04adff5bcb22d86a8
extra : source : f5b94d346fdbad4e611435e37a0ee8090fce439f
parent d81088d7
......@@ -18,7 +18,7 @@
namespace nss_test {
static const uint32_t kServerHelloVersionAlt = SSL_LIBRARY_VERSION_TLS_1_2;
static const uint32_t kServerHelloVersionRegular =
static const uint16_t kServerHelloVersionRegular =
0x7f00 | TLS_1_3_DRAFT_VERSION;
class AltHandshakeTest : public TlsConnectStreamTls13 {
......@@ -27,6 +27,8 @@ class AltHandshakeTest : public TlsConnectStreamTls13 {
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_ =
......@@ -42,11 +44,17 @@ class AltHandshakeTest : public TlsConnectStreamTls13 {
void InstallFilters() {
client_->SetPacketFilter(client_ccs_recorder_);
auto chain = std::make_shared<ChainedPacketFilter>(ChainedPacketFilterInit(
{server_ccs_recorder_, server_hello_recorder_}));
{server_handshake_recorder_, server_ccs_recorder_,
server_hello_recorder_}));
server_->SetPacketFilter(chain);
}
void CheckServerHelloVersion(uint32_t server_hello_version) {
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);
......@@ -56,15 +64,18 @@ class AltHandshakeTest : public TlsConnectStreamTls13 {
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_;
};
......
This diff is collapsed.
......@@ -495,7 +495,6 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
if (IS_DTLS(ss)) {
sslSequenceNumber seq_num;
cText.version = dtls_DTLSVersionToTLSVersion(cText.version);
/* DTLS sequence number */
PORT_Memcpy(&seq_num, &ss->gs.hdr[3], sizeof(seq_num));
cText.seq_num = PR_ntohll(seq_num);
......
......@@ -199,8 +199,6 @@ struct sslSocketOpsStr {
#define ssl_SEND_FLAG_FORCE_INTO_BUFFER 0x40000000
#define ssl_SEND_FLAG_NO_BUFFER 0x20000000
#define ssl_SEND_FLAG_NO_RETRANSMIT 0x08000000 /* DTLS only */
#define ssl_SEND_FLAG_CAP_RECORD_VERSION \
0x04000000 /* TLS only */
#define ssl_SEND_FLAG_MASK 0x7f000000
/*
......
......@@ -174,6 +174,26 @@ ssl_SetupNullCipherSpec(sslSocket *ss, CipherSpecDirection dir)
* own rules about construction of unencrypted records. For instance, TLS
* 1.3 will set the record version number to TLS 1.0. */
spec->version = ss->vrange.max;
if (IS_DTLS(ss)) {
spec->recordVersion = SSL_LIBRARY_VERSION_DTLS_1_0_WIRE;
} else {
/* For new connections, cap the record layer version number of TLS
* ClientHello to { 3, 1 } (TLS 1.0). Some TLS 1.0 servers (which seem
* to use F5 BIG-IP) ignore ClientHello.client_version and use the
* record layer version number (TLSPlaintext.version) instead when
* negotiating protocol versions. In addition, if the record layer
* version number of ClientHello is { 3, 2 } (TLS 1.1) or higher, these
* servers reset the TCP connections. Lastly, some F5 BIG-IP servers
* hang if a record containing a ClientHello has a version greater than
* { 3, 1 } and a length greater than 255. Set this flag to work around
* such servers.
*
* We bump the version up when we settle on a version. Before producing
* an initial ServerHello, or when processing it.
*/
spec->recordVersion = PR_MIN(SSL_LIBRARY_VERSION_TLS_1_0,
ss->vrange.max);
}
spec->cipherDef = &ssl_bulk_cipher_defs[cipher_null];
PORT_Assert(spec->cipherDef->cipher == cipher_null);
......
......@@ -148,6 +148,7 @@ struct ssl3CipherSpecStr {
CipherSpecDirection direction;
SSL3ProtocolVersion version;
SSL3ProtocolVersion recordVersion;
const ssl3BulkCipherDef *cipherDef;
const ssl3MACDef *macDef;
......
......@@ -132,9 +132,6 @@ const char keylogLabelExporterSecret[] = "EXPORTER_SECRET";
? ss->ssl3.hs.client##name \
: ss->ssl3.hs.server##name)
const SSL3ProtocolVersion kTlsRecordVersion = SSL_LIBRARY_VERSION_TLS_1_0;
const SSL3ProtocolVersion kDtlsRecordVersion = SSL_LIBRARY_VERSION_TLS_1_1;
/* Belt and suspenders in case we ever add a TLS 1.4. */
PR_STATIC_ASSERT(SSL_LIBRARY_VERSION_MAX_SUPPORTED <=
SSL_LIBRARY_VERSION_TLS_1_3);
......@@ -2961,12 +2958,40 @@ loser:
return SECFailure;
}
void
tls13_SetSpecRecordVersion(sslSocket *ss, ssl3CipherSpec *spec)
{
const SSL3ProtocolVersion kTlsRecordVersion = SSL_LIBRARY_VERSION_TLS_1_0;
const SSL3ProtocolVersion kTlsAltRecordVersion = SSL_LIBRARY_VERSION_TLS_1_2;
const SSL3ProtocolVersion kDtlsRecordVersion = SSL_LIBRARY_VERSION_DTLS_1_0_WIRE;
/* Set the record version. */
if (IS_DTLS(ss)) {
spec->recordVersion = kDtlsRecordVersion;
} else if (spec->epoch == TrafficKeyEarlyApplicationData) {
/* For early data, the previous session determines the record type that
* is used (and not what this session might negotiate). */
if (ss->sec.ci.sid && ss->sec.ci.sid->u.ssl3.altHandshakeType) {
spec->recordVersion = kTlsAltRecordVersion;
} else {
spec->recordVersion = kTlsRecordVersion;
}
} else if (ss->ssl3.hs.altHandshakeType) {
spec->recordVersion = kTlsAltRecordVersion;
} else {
spec->recordVersion = kTlsRecordVersion;
}
SSL_TRC(10, ("%d: TLS13[%d]: Set record version to 0x%04x",
SSL_GETPID(), ss->fd, spec->recordVersion));
}
static SECStatus
tls13_SetupPendingCipherSpec(sslSocket *ss, ssl3CipherSpec *spec)
{
ssl3CipherSuite suite = ss->ssl3.hs.cipher_suite;
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
PORT_Assert(spec->epoch);
/* Version isn't set when we send 0-RTT data. */
spec->version = PR_MAX(SSL_LIBRARY_VERSION_TLS_1_3, ss->version);
......@@ -2994,6 +3019,13 @@ tls13_SetupPendingCipherSpec(sslSocket *ss, ssl3CipherSpec *spec)
PORT_Assert(0);
return SECFailure;
}
if (spec->epoch == TrafficKeyEarlyApplicationData) {
spec->earlyDataRemaining =
ss->sec.ci.sid->u.ssl3.locked.sessionTicket.max_early_data_size;
}
tls13_SetSpecRecordVersion(ss, spec);
return SECSuccess;
}
......@@ -3053,9 +3085,6 @@ tls13_SetCipherSpec(sslSocket *ss, TrafficKeyType type,
if (!spec) {
return SECFailure;
}
rv = tls13_SetupPendingCipherSpec(ss, spec);
if (rv != SECSuccess)
return SECFailure;
specp = (direction == CipherSpecRead) ? &ss->ssl3.crSpec : &ss->ssl3.cwSpec;
......@@ -3069,9 +3098,11 @@ tls13_SetCipherSpec(sslSocket *ss, TrafficKeyType type,
if (IS_DTLS(ss)) {
dtls_InitRecvdRecords(&spec->recvdRecords);
}
if (type == TrafficKeyEarlyApplicationData) {
spec->earlyDataRemaining =
ss->sec.ci.sid->u.ssl3.locked.sessionTicket.max_early_data_size;
/* This depends on spec having a valid direction and epoch. */
rv = tls13_SetupPendingCipherSpec(ss, spec);
if (rv != SECSuccess) {
return SECFailure;
}
rv = tls13_DeriveTrafficKeys(ss, spec, type, deleteSecret);
......@@ -4679,9 +4710,8 @@ tls13_UnprotectRecord(sslSocket *ss,
return SECFailure;
}
/* Check the version number in the record */
if ((IS_DTLS(ss) && cText->version != kDtlsRecordVersion) ||
(!IS_DTLS(ss) && cText->version != kTlsRecordVersion)) {
/* Check the version number in the record. */
if (cText->version != spec->recordVersion) {
/* Do we need a better error here? */
SSL_TRC(3,
("%d: TLS13[%d]: record has bogus version",
......@@ -5017,14 +5047,14 @@ tls13_NegotiateVersion(sslSocket *ss, const TLSExtension *supported_versions)
if (ss->opt.enableAltHandshaketype &&
!IS_DTLS(ss) &&
supported == alt_wire) {
ss->version = version;
ss->ssl3.hs.altHandshakeType = PR_TRUE;
rv = ssl3_RegisterExtensionSender(ss, &ss->xtnData,
ssl_tls13_supported_versions_xtn,
tls13_ServerSendSupportedVersionsXtn);
if (rv != SECSuccess) {
return SECFailure;
}
ss->ssl3.hs.altHandshakeType = PR_TRUE;
ss->version = version;
return SECSuccess;
}
}
......
......@@ -110,5 +110,6 @@ SECStatus SSLExp_HelloRetryRequestCallback(PRFileDesc *fd,
void *arg);
SECStatus SSLExp_UseAltHandshakeType(PRFileDesc *fd, PRBool enable);
PRBool tls13_MaybeTls13(sslSocket *ss);
void tls13_SetSpecRecordVersion(sslSocket *ss, ssl3CipherSpec *spec);
#endif /* __tls13con_h_ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment