summaryrefslogtreecommitdiff
path: root/backport-CVE-2020-25648-tighten-CSS-handling-in-compatibility-mode.patch
diff options
context:
space:
mode:
Diffstat (limited to 'backport-CVE-2020-25648-tighten-CSS-handling-in-compatibility-mode.patch')
-rw-r--r--backport-CVE-2020-25648-tighten-CSS-handling-in-compatibility-mode.patch122
1 files changed, 122 insertions, 0 deletions
diff --git a/backport-CVE-2020-25648-tighten-CSS-handling-in-compatibility-mode.patch b/backport-CVE-2020-25648-tighten-CSS-handling-in-compatibility-mode.patch
new file mode 100644
index 0000000..fc0a5bd
--- /dev/null
+++ b/backport-CVE-2020-25648-tighten-CSS-handling-in-compatibility-mode.patch
@@ -0,0 +1,122 @@
+From e10a362f69191506e73bfa31778da45f4c5df482 Mon Sep 17 00:00:00 2001
+From: Daiki Ueno <dueno@redhat.com>
+Date: Mon, 12 Oct 2020 17:42:01 +0000
+Subject: [PATCH] Bug 1641480, TLS 1.3: tighten CCS handling in compatibility
+ mode, r=mt
+
+This makes the server reject CCS when the client doesn't indicate the
+use of the middlebox compatibility mode with a non-empty
+ClientHello.legacy_session_id, or it sends multiple CCS in a row.
+
+Differential Revision: https://phabricator.services.mozilla.com/D79994
+
+--HG--
+extra : moz-landing-system : lando
+---
+ gtests/ssl_gtest/ssl_tls13compat_unittest.cc | 33 ++++++++++++++++++++
+ lib/ssl/ssl3con.c | 18 ++++-
+ lib/ssl/sslimpl.h | 4 +
+ 3 files changed, 52 insertions(+), 3 deletions(-)
+
+diff --git a/nss/gtests/ssl_gtest/ssl_tls13compat_unittest.cc b/nss/gtests/ssl_gtest/ssl_tls13compat_unittest.cc
+index 6905ed0c0..dcede798c 100644
+--- a/nss/gtests/ssl_gtest/ssl_tls13compat_unittest.cc
++++ b/nss/gtests/ssl_gtest/ssl_tls13compat_unittest.cc
+@@ -348,6 +348,39 @@ TEST_F(TlsConnectStreamTls13, ChangeCipherSpecBeforeClientHelloTwice) {
+ client_->CheckErrorCode(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT);
+ }
+
++// The server rejects a ChangeCipherSpec if the client advertises an
++// empty session ID.
++TEST_F(TlsConnectStreamTls13, ChangeCipherSpecAfterClientHelloEmptySid) {
++ EnsureTlsSetup();
++ ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
++
++ StartConnect();
++ client_->Handshake(); // Send ClientHello
++ client_->SendDirect(DataBuffer(kCannedCcs, sizeof(kCannedCcs))); // Send CCS
++
++ server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
++ server_->Handshake(); // Consume ClientHello and CCS
++ server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER);
++}
++
++// The server rejects multiple ChangeCipherSpec even if the client
++// indicates compatibility mode with non-empty session ID.
++TEST_F(Tls13CompatTest, ChangeCipherSpecAfterClientHelloTwice) {
++ EnsureTlsSetup();
++ ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
++ EnableCompatMode();
++
++ StartConnect();
++ client_->Handshake(); // Send ClientHello
++ // Send CCS twice in a row
++ client_->SendDirect(DataBuffer(kCannedCcs, sizeof(kCannedCcs)));
++ client_->SendDirect(DataBuffer(kCannedCcs, sizeof(kCannedCcs)));
++
++ server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
++ server_->Handshake(); // Consume ClientHello and CCS.
++ server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER);
++}
++
+ // If we negotiate 1.2, we abort.
+ TEST_F(TlsConnectStreamTls13, ChangeCipherSpecBeforeClientHello12) {
+ EnsureTlsSetup();
+diff --git a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c
+index 8be53d357..5f22872f8 100644
+--- a/nss/lib/ssl/ssl3con.c
++++ b/nss/lib/ssl/ssl3con.c
+@@ -6645,7 +6645,11 @@ ssl_CheckServerSessionIdCorrectness(sslSocket *ss, SECItem *sidBytes)
+
+ /* TLS 1.3: We sent a session ID. The server's should match. */
+ if (!IS_DTLS(ss) && (sentRealSid || sentFakeSid)) {
+- return sidMatch;
++ if (sidMatch) {
++ ss->ssl3.hs.allowCcs = PR_TRUE;
++ return PR_TRUE;
++ }
++ return PR_FALSE;
+ }
+
+ /* TLS 1.3 (no SID)/DTLS 1.3: The server shouldn't send a session ID. */
+@@ -8692,6 +8696,7 @@ ssl3_HandleClientHello(sslSocket *ss, PRUint8 *b, PRUint32 length)
+ errCode = PORT_GetError();
+ goto alert_loser;
+ }
++ ss->ssl3.hs.allowCcs = PR_TRUE;
+ }
+
+ /* TLS 1.3 requires that compression include only null. */
+@@ -13061,8 +13066,15 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText)
+ ss->ssl3.hs.ws != idle_handshake &&
+ cText->buf->len == 1 &&
+ cText->buf->buf[0] == change_cipher_spec_choice) {
+- /* Ignore the CCS. */
+- return SECSuccess;
++ if (ss->ssl3.hs.allowCcs) {
++ /* Ignore the first CCS. */
++ ss->ssl3.hs.allowCcs = PR_FALSE;
++ return SECSuccess;
++ }
++
++ /* Compatibility mode is not negotiated. */
++ alert = unexpected_message;
++ PORT_SetError(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER);
+ }
+
+ if (IS_DTLS(ss) ||
+diff --git a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h
+index b0e44a088..44c43a0e6 100644
+--- a/nss/lib/ssl/sslimpl.h
++++ b/nss/lib/ssl/sslimpl.h
+@@ -710,6 +710,10 @@ typedef struct SSL3HandshakeStateStr {
+ * or received. */
+ PRBool receivedCcs; /* A server received ChangeCipherSpec
+ * before the handshake started. */
++ PRBool allowCcs; /* A server allows ChangeCipherSpec
++ * as the middlebox compatibility mode
++ * is explicitly indicarted by
++ * legacy_session_id in TLS 1.3 ClientHello. */
+ PRBool clientCertRequested; /* True if CertificateRequest received. */
+ ssl3KEADef kea_def_mutable; /* Used to hold the writable kea_def
+ * we use for TLS 1.3 */