summaryrefslogtreecommitdiff
path: root/dev-libs/nss/files/nss-3.58-always-tolerate-the-first-CCS-in-TLS1.3.patch
diff options
context:
space:
mode:
Diffstat (limited to 'dev-libs/nss/files/nss-3.58-always-tolerate-the-first-CCS-in-TLS1.3.patch')
-rw-r--r--dev-libs/nss/files/nss-3.58-always-tolerate-the-first-CCS-in-TLS1.3.patch200
1 files changed, 200 insertions, 0 deletions
diff --git a/dev-libs/nss/files/nss-3.58-always-tolerate-the-first-CCS-in-TLS1.3.patch b/dev-libs/nss/files/nss-3.58-always-tolerate-the-first-CCS-in-TLS1.3.patch
new file mode 100644
index 000000000000..a92c03899360
--- /dev/null
+++ b/dev-libs/nss/files/nss-3.58-always-tolerate-the-first-CCS-in-TLS1.3.patch
@@ -0,0 +1,200 @@
+
+# HG changeset patch
+# User Daiki Ueno <dueno@redhat.com>
+# Date 1603691171 -3600
+# Node ID b03a4fc5b902498414b02640dcb2717dfef9682f
+# Parent 6f79a76958129dc09c353c288f115fd9a51ab7d4
+Bug 1672703, always tolerate the first CCS in TLS 1.3, r=mt
+
+Summary:
+This flips the meaning of the flag for checking excessive CCS
+messages, so it only rejects multiple CCS messages while the first CCS
+message is always accepted.
+
+Reviewers: mt
+
+Reviewed By: mt
+
+Bug #: 1672703
+
+Differential Revision: https://phabricator.services.mozilla.com/D94603
+
+--- a/gtests/ssl_gtest/ssl_tls13compat_unittest.cc
++++ b/gtests/ssl_gtest/ssl_tls13compat_unittest.cc
+@@ -343,29 +343,28 @@ TEST_F(TlsConnectStreamTls13, ChangeCiph
+ // Client sends CCS before starting the handshake.
+ client_->SendDirect(DataBuffer(kCannedCcs, sizeof(kCannedCcs)));
+ client_->SendDirect(DataBuffer(kCannedCcs, sizeof(kCannedCcs)));
+ ConnectExpectAlert(server_, kTlsAlertUnexpectedMessage);
+ server_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER);
+ client_->CheckErrorCode(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT);
+ }
+
+-// The server rejects a ChangeCipherSpec if the client advertises an
+-// empty session ID.
++// The server accepts a ChangeCipherSpec even 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);
++ Handshake();
++ CheckConnected();
+ }
+
+ // 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();
+@@ -376,36 +375,37 @@ TEST_F(Tls13CompatTest, ChangeCipherSpec
+ 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);
+ }
+
+-// The client rejects a ChangeCipherSpec if it advertises an empty
++// The client accepts a ChangeCipherSpec even if it advertises an empty
+ // session ID.
+ TEST_F(TlsConnectStreamTls13, ChangeCipherSpecAfterServerHelloEmptySid) {
+ EnsureTlsSetup();
+ ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
+
+ // To replace Finished with a CCS below
+ auto filter = MakeTlsFilter<TlsHandshakeDropper>(server_);
+ filter->SetHandshakeTypes({kTlsHandshakeFinished});
+ filter->EnableDecryption();
+
+ StartConnect();
+ client_->Handshake(); // Send ClientHello
+ server_->Handshake(); // Consume ClientHello, and
+ // send ServerHello..CertificateVerify
+ // Send CCS
+ server_->SendDirect(DataBuffer(kCannedCcs, sizeof(kCannedCcs)));
+- client_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
+- client_->Handshake(); // Consume ClientHello and CCS
+- client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER);
++
++ // No alert is sent from the client. As Finished is dropped, we
++ // can't use Handshake() and CheckConnected().
++ client_->Handshake();
+ }
+
+ // The client rejects multiple ChangeCipherSpec in a row even if the
+ // client indicates compatibility mode with non-empty session ID.
+ TEST_F(Tls13CompatTest, ChangeCipherSpecAfterServerHelloTwice) {
+ EnsureTlsSetup();
+ ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
+ EnableCompatMode();
+--- a/lib/ssl/ssl3con.c
++++ b/lib/ssl/ssl3con.c
+@@ -6640,21 +6640,17 @@ ssl_CheckServerSessionIdCorrectness(sslS
+ if (sentFakeSid) {
+ return !sidMatch;
+ }
+ return PR_TRUE;
+ }
+
+ /* TLS 1.3: We sent a session ID. The server's should match. */
+ if (!IS_DTLS(ss) && (sentRealSid || sentFakeSid)) {
+- if (sidMatch) {
+- ss->ssl3.hs.allowCcs = PR_TRUE;
+- return PR_TRUE;
+- }
+- return PR_FALSE;
++ return sidMatch;
+ }
+
+ /* TLS 1.3 (no SID)/DTLS 1.3: The server shouldn't send a session ID. */
+ return sidBytes->len == 0;
+ }
+
+ static SECStatus
+ ssl_CheckServerRandom(sslSocket *ss)
+@@ -8691,17 +8687,16 @@ ssl3_HandleClientHello(sslSocket *ss, PR
+ if (sidBytes.len > 0 && !IS_DTLS(ss)) {
+ SECITEM_FreeItem(&ss->ssl3.hs.fakeSid, PR_FALSE);
+ rv = SECITEM_CopyItem(NULL, &ss->ssl3.hs.fakeSid, &sidBytes);
+ if (rv != SECSuccess) {
+ desc = internal_error;
+ errCode = PORT_GetError();
+ goto alert_loser;
+ }
+- ss->ssl3.hs.allowCcs = PR_TRUE;
+ }
+
+ /* TLS 1.3 requires that compression include only null. */
+ if (comps.len != 1 || comps.data[0] != ssl_compression_null) {
+ goto alert_loser;
+ }
+
+ /* If there is a cookie, then this is a second ClientHello (TLS 1.3). */
+@@ -13061,25 +13056,24 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Cip
+ * will fail if the server fails to negotiate compatibility mode in a
+ * 0-RTT session that is resumed from a session that did negotiate it.
+ * We don't care about that corner case right now. */
+ if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 &&
+ cText->hdr[0] == ssl_ct_change_cipher_spec &&
+ ss->ssl3.hs.ws != idle_handshake &&
+ cText->buf->len == 1 &&
+ cText->buf->buf[0] == change_cipher_spec_choice) {
+- if (ss->ssl3.hs.allowCcs) {
+- /* Ignore the first CCS. */
+- ss->ssl3.hs.allowCcs = PR_FALSE;
++ if (!ss->ssl3.hs.rejectCcs) {
++ /* Allow only the first CCS. */
++ ss->ssl3.hs.rejectCcs = PR_TRUE;
+ return SECSuccess;
+- }
+-
+- /* Compatibility mode is not negotiated. */
+- alert = unexpected_message;
+- PORT_SetError(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER);
++ } else {
++ alert = unexpected_message;
++ PORT_SetError(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER);
++ }
+ }
+
+ if ((IS_DTLS(ss) && !dtls13_AeadLimitReached(spec)) ||
+ (!IS_DTLS(ss) && ss->sec.isServer &&
+ ss->ssl3.hs.zeroRttIgnore == ssl_0rtt_ignore_trial)) {
+ /* Silently drop the packet unless we sent a fatal alert. */
+ if (ss->ssl3.fatalAlertSent) {
+ return SECFailure;
+--- a/lib/ssl/sslimpl.h
++++ b/lib/ssl/sslimpl.h
+@@ -705,20 +705,17 @@ typedef struct SSL3HandshakeStateStr {
+ sslZeroRttIgnore zeroRttIgnore; /* Are we ignoring 0-RTT? */
+ ssl3CipherSuite zeroRttSuite; /* The cipher suite we used for 0-RTT. */
+ PRCList bufferedEarlyData; /* Buffered TLS 1.3 early data
+ * on server.*/
+ PRBool helloRetry; /* True if HelloRetryRequest has been sent
+ * 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 rejectCcs; /* Excessive ChangeCipherSpecs are rejected. */
+ PRBool clientCertRequested; /* True if CertificateRequest received. */
+ PRBool endOfFlight; /* Processed a full flight (DTLS 1.3). */
+ ssl3KEADef kea_def_mutable; /* Used to hold the writable kea_def
+ * we use for TLS 1.3 */
+ PRUint16 ticketNonce; /* A counter we use for tickets. */
+ SECItem fakeSid; /* ... (server) the SID the client used. */
+
+ /* rttEstimate is used to guess the round trip time between server and client.
+