Line 0
Link Here
|
|
|
1 |
diff --git a/gtests/ssl_gtest/ssl_tls13compat_unittest.cc b/gtests/ssl_gtest/ssl_tls13compat_unittest.cc |
2 |
--- gtests/ssl_gtest/ssl_tls13compat_unittest.cc |
3 |
+++ gtests/ssl_gtest/ssl_tls13compat_unittest.cc |
4 |
@@ -343,29 +343,28 @@ TEST_F(TlsConnectStreamTls13, ChangeCiph |
5 |
// Client sends CCS before starting the handshake. |
6 |
client_->SendDirect(DataBuffer(kCannedCcs, sizeof(kCannedCcs))); |
7 |
client_->SendDirect(DataBuffer(kCannedCcs, sizeof(kCannedCcs))); |
8 |
ConnectExpectAlert(server_, kTlsAlertUnexpectedMessage); |
9 |
server_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER); |
10 |
client_->CheckErrorCode(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT); |
11 |
} |
12 |
|
13 |
-// The server rejects a ChangeCipherSpec if the client advertises an |
14 |
-// empty session ID. |
15 |
+// The server accepts a ChangeCipherSpec even if the client advertises |
16 |
+// an empty session ID. |
17 |
TEST_F(TlsConnectStreamTls13, ChangeCipherSpecAfterClientHelloEmptySid) { |
18 |
EnsureTlsSetup(); |
19 |
ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3); |
20 |
|
21 |
StartConnect(); |
22 |
client_->Handshake(); // Send ClientHello |
23 |
client_->SendDirect(DataBuffer(kCannedCcs, sizeof(kCannedCcs))); // Send CCS |
24 |
|
25 |
- server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); |
26 |
- server_->Handshake(); // Consume ClientHello and CCS |
27 |
- server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER); |
28 |
+ Handshake(); |
29 |
+ CheckConnected(); |
30 |
} |
31 |
|
32 |
// The server rejects multiple ChangeCipherSpec even if the client |
33 |
// indicates compatibility mode with non-empty session ID. |
34 |
TEST_F(Tls13CompatTest, ChangeCipherSpecAfterClientHelloTwice) { |
35 |
EnsureTlsSetup(); |
36 |
ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3); |
37 |
EnableCompatMode(); |
38 |
@@ -376,36 +375,37 @@ TEST_F(Tls13CompatTest, ChangeCipherSpec |
39 |
client_->SendDirect(DataBuffer(kCannedCcs, sizeof(kCannedCcs))); |
40 |
client_->SendDirect(DataBuffer(kCannedCcs, sizeof(kCannedCcs))); |
41 |
|
42 |
server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); |
43 |
server_->Handshake(); // Consume ClientHello and CCS. |
44 |
server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER); |
45 |
} |
46 |
|
47 |
-// The client rejects a ChangeCipherSpec if it advertises an empty |
48 |
+// The client accepts a ChangeCipherSpec even if it advertises an empty |
49 |
// session ID. |
50 |
TEST_F(TlsConnectStreamTls13, ChangeCipherSpecAfterServerHelloEmptySid) { |
51 |
EnsureTlsSetup(); |
52 |
ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3); |
53 |
|
54 |
// To replace Finished with a CCS below |
55 |
auto filter = MakeTlsFilter<TlsHandshakeDropper>(server_); |
56 |
filter->SetHandshakeTypes({kTlsHandshakeFinished}); |
57 |
filter->EnableDecryption(); |
58 |
|
59 |
StartConnect(); |
60 |
client_->Handshake(); // Send ClientHello |
61 |
server_->Handshake(); // Consume ClientHello, and |
62 |
// send ServerHello..CertificateVerify |
63 |
// Send CCS |
64 |
server_->SendDirect(DataBuffer(kCannedCcs, sizeof(kCannedCcs))); |
65 |
- client_->ExpectSendAlert(kTlsAlertUnexpectedMessage); |
66 |
- client_->Handshake(); // Consume ClientHello and CCS |
67 |
- client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER); |
68 |
+ |
69 |
+ // No alert is sent from the client. As Finished is dropped, we |
70 |
+ // can't use Handshake() and CheckConnected(). |
71 |
+ client_->Handshake(); |
72 |
} |
73 |
|
74 |
// The client rejects multiple ChangeCipherSpec in a row even if the |
75 |
// client indicates compatibility mode with non-empty session ID. |
76 |
TEST_F(Tls13CompatTest, ChangeCipherSpecAfterServerHelloTwice) { |
77 |
EnsureTlsSetup(); |
78 |
ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3); |
79 |
EnableCompatMode(); |
80 |
diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c |
81 |
--- lib/ssl/ssl3con.c |
82 |
+++ lib/ssl/ssl3con.c |
83 |
@@ -6640,21 +6640,17 @@ ssl_CheckServerSessionIdCorrectness(sslS |
84 |
if (sentFakeSid) { |
85 |
return !sidMatch; |
86 |
} |
87 |
return PR_TRUE; |
88 |
} |
89 |
|
90 |
/* TLS 1.3: We sent a session ID. The server's should match. */ |
91 |
if (!IS_DTLS(ss) && (sentRealSid || sentFakeSid)) { |
92 |
- if (sidMatch) { |
93 |
- ss->ssl3.hs.allowCcs = PR_TRUE; |
94 |
- return PR_TRUE; |
95 |
- } |
96 |
- return PR_FALSE; |
97 |
+ return sidMatch; |
98 |
} |
99 |
|
100 |
/* TLS 1.3 (no SID)/DTLS 1.3: The server shouldn't send a session ID. */ |
101 |
return sidBytes->len == 0; |
102 |
} |
103 |
|
104 |
static SECStatus |
105 |
ssl_CheckServerRandom(sslSocket *ss) |
106 |
@@ -8691,17 +8687,16 @@ ssl3_HandleClientHello(sslSocket *ss, PR |
107 |
if (sidBytes.len > 0 && !IS_DTLS(ss)) { |
108 |
SECITEM_FreeItem(&ss->ssl3.hs.fakeSid, PR_FALSE); |
109 |
rv = SECITEM_CopyItem(NULL, &ss->ssl3.hs.fakeSid, &sidBytes); |
110 |
if (rv != SECSuccess) { |
111 |
desc = internal_error; |
112 |
errCode = PORT_GetError(); |
113 |
goto alert_loser; |
114 |
} |
115 |
- ss->ssl3.hs.allowCcs = PR_TRUE; |
116 |
} |
117 |
|
118 |
/* TLS 1.3 requires that compression include only null. */ |
119 |
if (comps.len != 1 || comps.data[0] != ssl_compression_null) { |
120 |
goto alert_loser; |
121 |
} |
122 |
|
123 |
/* If there is a cookie, then this is a second ClientHello (TLS 1.3). */ |
124 |
@@ -13061,25 +13056,24 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Cip |
125 |
* will fail if the server fails to negotiate compatibility mode in a |
126 |
* 0-RTT session that is resumed from a session that did negotiate it. |
127 |
* We don't care about that corner case right now. */ |
128 |
if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 && |
129 |
cText->hdr[0] == ssl_ct_change_cipher_spec && |
130 |
ss->ssl3.hs.ws != idle_handshake && |
131 |
cText->buf->len == 1 && |
132 |
cText->buf->buf[0] == change_cipher_spec_choice) { |
133 |
- if (ss->ssl3.hs.allowCcs) { |
134 |
- /* Ignore the first CCS. */ |
135 |
- ss->ssl3.hs.allowCcs = PR_FALSE; |
136 |
+ if (!ss->ssl3.hs.rejectCcs) { |
137 |
+ /* Allow only the first CCS. */ |
138 |
+ ss->ssl3.hs.rejectCcs = PR_TRUE; |
139 |
return SECSuccess; |
140 |
- } |
141 |
- |
142 |
- /* Compatibility mode is not negotiated. */ |
143 |
- alert = unexpected_message; |
144 |
- PORT_SetError(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER); |
145 |
+ } else { |
146 |
+ alert = unexpected_message; |
147 |
+ PORT_SetError(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER); |
148 |
+ } |
149 |
} |
150 |
|
151 |
if ((IS_DTLS(ss) && !dtls13_AeadLimitReached(spec)) || |
152 |
(!IS_DTLS(ss) && ss->sec.isServer && |
153 |
ss->ssl3.hs.zeroRttIgnore == ssl_0rtt_ignore_trial)) { |
154 |
/* Silently drop the packet unless we sent a fatal alert. */ |
155 |
if (ss->ssl3.fatalAlertSent) { |
156 |
return SECFailure; |
157 |
diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h |
158 |
--- lib/ssl/sslimpl.h |
159 |
+++ lib/ssl/sslimpl.h |
160 |
@@ -705,20 +705,17 @@ typedef struct SSL3HandshakeStateStr { |
161 |
sslZeroRttIgnore zeroRttIgnore; /* Are we ignoring 0-RTT? */ |
162 |
ssl3CipherSuite zeroRttSuite; /* The cipher suite we used for 0-RTT. */ |
163 |
PRCList bufferedEarlyData; /* Buffered TLS 1.3 early data |
164 |
* on server.*/ |
165 |
PRBool helloRetry; /* True if HelloRetryRequest has been sent |
166 |
* or received. */ |
167 |
PRBool receivedCcs; /* A server received ChangeCipherSpec |
168 |
* before the handshake started. */ |
169 |
- PRBool allowCcs; /* A server allows ChangeCipherSpec |
170 |
- * as the middlebox compatibility mode |
171 |
- * is explicitly indicarted by |
172 |
- * legacy_session_id in TLS 1.3 ClientHello. */ |
173 |
+ PRBool rejectCcs; /* Excessive ChangeCipherSpecs are rejected. */ |
174 |
PRBool clientCertRequested; /* True if CertificateRequest received. */ |
175 |
PRBool endOfFlight; /* Processed a full flight (DTLS 1.3). */ |
176 |
ssl3KEADef kea_def_mutable; /* Used to hold the writable kea_def |
177 |
* we use for TLS 1.3 */ |
178 |
PRUint16 ticketNonce; /* A counter we use for tickets. */ |
179 |
SECItem fakeSid; /* ... (server) the SID the client used. */ |
180 |
|
181 |
/* rttEstimate is used to guess the round trip time between server and client. |
182 |
|