summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Thomson <martin.thomson@gmail.com>2018-05-18 12:51:29 +1000
committerMartin Thomson <martin.thomson@gmail.com>2018-05-18 12:51:29 +1000
commit08842869dc8c12d0622f63f111628ed36c3079f0 (patch)
treebff6d8c7ca17e3be8bdf3a3a365336dae8b69608
parentecd9c58a97a3493825c8009bcef0a71b5f77d940 (diff)
downloadnss-hg-08842869dc8c12d0622f63f111628ed36c3079f0.tar.gz
Bug 1462303 - Allow TLS 1.3 compat mode when attempting to resume TLS 1.2, r=ekr,ttaubert
-rw-r--r--gtests/ssl_gtest/ssl_tls13compat_unittest.cc16
-rw-r--r--lib/ssl/ssl3con.c40
2 files changed, 41 insertions, 15 deletions
diff --git a/gtests/ssl_gtest/ssl_tls13compat_unittest.cc b/gtests/ssl_gtest/ssl_tls13compat_unittest.cc
index f4ea58e10..42f1065f6 100644
--- a/gtests/ssl_gtest/ssl_tls13compat_unittest.cc
+++ b/gtests/ssl_gtest/ssl_tls13compat_unittest.cc
@@ -436,4 +436,20 @@ TEST_F(TlsConnectDatagram13, CompatModeDtlsServer) {
EXPECT_EQ(0U, session_id_len);
}
+TEST_F(Tls13CompatTest, ConnectWith12ThenAttemptToResume13CompatMode) {
+ ConfigureSessionCache(RESUME_SESSIONID, RESUME_SESSIONID);
+ ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_2);
+ Connect();
+
+ Reset();
+ ExpectResumption(RESUME_NONE);
+ version_ = SSL_LIBRARY_VERSION_TLS_1_3;
+ client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
+ SSL_LIBRARY_VERSION_TLS_1_3);
+ server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
+ SSL_LIBRARY_VERSION_TLS_1_3);
+ EnableCompatMode();
+ Connect();
+}
+
} // namespace nss_test
diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
index 5f7b7b84c..00e130786 100644
--- a/lib/ssl/ssl3con.c
+++ b/lib/ssl/ssl3con.c
@@ -6164,28 +6164,38 @@ ssl_ClientSetCipherSuite(sslSocket *ss, SSL3ProtocolVersion version,
static PRBool
ssl_CheckServerSessionIdCorrectness(sslSocket *ss, SECItem *sidBytes)
{
- PRBool sid_match = PR_FALSE;
- PRBool sent_fake_sid = ss->opt.enableTls13CompatMode && !IS_DTLS(ss);
-
- /* If in compat mode and we received a session ID with the right length
- * then compare it to the fake one we sent in the ClientHello. */
- if (sent_fake_sid && sidBytes->len == SSL3_SESSIONID_BYTES) {
- PRUint8 buf[SSL3_SESSIONID_BYTES];
- ssl_MakeFakeSid(ss, buf);
- sid_match = PORT_Memcmp(buf, sidBytes->data, sidBytes->len) == 0;
+ sslSessionID *sid = ss->sec.ci.sid;
+ PRBool sidMatch = PR_FALSE;
+ PRBool sentFakeSid = PR_FALSE;
+ PRBool sentRealSid = sid && sid->version < SSL_LIBRARY_VERSION_TLS_1_3;
+
+ /* If attempting to resume a TLS 1.2 connection, the session ID won't be a
+ * fake. Check for the real value. */
+ if (sentRealSid) {
+ sidMatch = (sidBytes->len == sid->u.ssl3.sessionIDLength) &&
+ PORT_Memcmp(sid->u.ssl3.sessionID, sidBytes->data, sidBytes->len) == 0;
+ } else {
+ /* Otherwise, the session ID was a fake if TLS 1.3 compat mode is
+ * enabled. If so, check for the fake value. */
+ sentFakeSid = ss->opt.enableTls13CompatMode && !IS_DTLS(ss);
+ if (sentFakeSid && sidBytes->len == SSL3_SESSIONID_BYTES) {
+ PRUint8 buf[SSL3_SESSIONID_BYTES];
+ ssl_MakeFakeSid(ss, buf);
+ sidMatch = PORT_Memcmp(buf, sidBytes->data, sidBytes->len) == 0;
+ }
}
- /* TLS 1.2: SessionID shouldn't match the fake one. */
+ /* TLS 1.2: Session ID shouldn't match if we sent a fake. */
if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
- return !sid_match;
+ return !sentFakeSid || !sidMatch;
}
- /* TLS 1.3: [Compat Mode] Session ID should match the fake one. */
- if (sent_fake_sid) {
- return sid_match;
+ /* TLS 1.3: We sent a session ID. The server's should match. */
+ if (sentRealSid || sentFakeSid) {
+ return sidMatch;
}
- /* TLS 1.3: [Non-Compat Mode] Server shouldn't send a session ID. */
+ /* TLS 1.3: The server shouldn't send a session ID. */
return sidBytes->len == 0;
}