Skip to content

Commit de02dc5

Browse files
committed
Bug 1879954 - exempt errors after Server Hello from Xyber retry logic. r=keeler
Differential Revision: https://phabricator.services.mozilla.com/D201638
1 parent b09e6c0 commit de02dc5

File tree

7 files changed

+90
-38
lines changed

7 files changed

+90
-38
lines changed

security/manager/ssl/NSSSocketControl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ NSSSocketControl::NSSSocketControl(const nsCString& aHostName, int32_t aPort,
3838
mNotedTimeUntilReady(false),
3939
mEchExtensionStatus(EchExtensionStatus::kNotPresent),
4040
mSentXyberShare(false),
41+
mHasTls13HandshakeSecrets(false),
4142
mIsShortWritePending(false),
4243
mShortWritePendingByte(0),
4344
mShortWriteOriginalAmount(-1),

security/manager/ssl/NSSSocketControl.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,16 @@ class NSSSocketControl final : public CommonSocketControl {
125125
return mSentXyberShare;
126126
}
127127

128+
void SetHasTls13HandshakeSecrets() {
129+
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
130+
mHasTls13HandshakeSecrets = true;
131+
}
132+
133+
bool HasTls13HandshakeSecrets() {
134+
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
135+
return mHasTls13HandshakeSecrets;
136+
}
137+
128138
bool GetJoined() {
129139
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
130140
return mJoined;
@@ -296,6 +306,7 @@ class NSSSocketControl final : public CommonSocketControl {
296306
bool mNotedTimeUntilReady;
297307
EchExtensionStatus mEchExtensionStatus; // Currently only used for telemetry.
298308
bool mSentXyberShare;
309+
bool mHasTls13HandshakeSecrets;
299310

300311
// True when SSL layer has indicated an "SSL short write", i.e. need
301312
// to call on send one or more times to push all pending data to write.

security/manager/ssl/nsNSSCallbacks.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,3 +1137,16 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) {
11371137
infoObject->NoteTimeUntilReady();
11381138
infoObject->SetHandshakeCompleted();
11391139
}
1140+
1141+
void SecretCallback(PRFileDesc* fd, PRUint16 epoch, SSLSecretDirection dir,
1142+
PK11SymKey* secret, void* arg) {
1143+
// arg must be set to an NSSSocketControl* in SSL_SecretCallback
1144+
MOZ_ASSERT(arg);
1145+
NSSSocketControl* infoObject = (NSSSocketControl*)arg;
1146+
if (epoch == 2 && dir == ssl_secret_read) {
1147+
// |secret| is the server_handshake_traffic_secret. Set a flag to indicate
1148+
// that the Server Hello has been processed successfully. We use this when
1149+
// deciding whether to retry a connection in which a Xyber share was sent.
1150+
infoObject->SetHasTls13HandshakeSecrets();
1151+
}
1152+
}

security/manager/ssl/nsNSSCallbacks.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "mozpkix/pkix.h"
1818
#include "mozpkix/pkixtypes.h"
1919
#include "nsIX509Cert.h"
20+
#include "ssl.h"
2021

2122
using mozilla::OriginAttributes;
2223
using mozilla::TimeDuration;
@@ -27,6 +28,8 @@ class nsILoadGroup;
2728
char* PK11PasswordPrompt(PK11SlotInfo* slot, PRBool retry, void* arg);
2829

2930
void HandshakeCallback(PRFileDesc* fd, void* client_data);
31+
void SecretCallback(PRFileDesc* fd, PRUint16 epoch, SSLSecretDirection dir,
32+
PK11SymKey* secret, void* arg);
3033
SECStatus CanFalseStartCallback(PRFileDesc* fd, void* client_data,
3134
PRBool* canFalseStart);
3235

security/manager/ssl/nsNSSIOLayer.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ bool retryDueToTLSIntolerance(PRErrorCode err, NSSSocketControl* socketInfo) {
446446
}
447447

448448
if (!socketInfo->IsPreliminaryHandshakeDone() &&
449-
socketInfo->SentXyberShare()) {
449+
!socketInfo->HasTls13HandshakeSecrets() && socketInfo->SentXyberShare()) {
450450
nsAutoCString errorName;
451451
const char* prErrorName = PR_ErrorToName(err);
452452
if (prErrorName) {
@@ -1279,6 +1279,9 @@ static PRFileDesc* nsSSLIOLayerImportFD(PRFileDesc* fd,
12791279
SECSuccess) {
12801280
return nullptr;
12811281
}
1282+
if (SSL_SecretCallback(sslSock, SecretCallback, infoObject) != SECSuccess) {
1283+
return nullptr;
1284+
}
12821285
if (SSL_SetCanFalseStartCallback(sslSock, CanFalseStartCallback,
12831286
infoObject) != SECSuccess) {
12841287
return nullptr;

security/manager/ssl/tests/unit/test_faulty_server.js

Lines changed: 53 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -73,50 +73,70 @@ add_task(
7373
skip_if: () => AppConstants.MOZ_SYSTEM_NSS,
7474
},
7575
async function testRetryXyber() {
76-
const retryDomains = [
77-
"xyber-net-interrupt.example.com",
78-
"xyber-alert-unexpected.example.com",
79-
];
76+
const retryDomain = "xyber-net-interrupt.example.com";
8077

8178
Services.prefs.setBoolPref("security.tls.enable_kyber", true);
82-
Services.prefs.setCharPref("network.dns.localDomains", retryDomains);
79+
Services.prefs.setCharPref("network.dns.localDomains", [retryDomain]);
8380
Services.prefs.setIntPref("network.http.speculative-parallel-limit", 0);
8481

85-
for (let i = 0; i < retryDomains.length; i++) {
86-
// Get the number of xyber / x25519 callbacks prior to making the request
87-
// ssl_grp_kem_xyber768d00 = 25497
88-
// ssl_grp_ec_curve25519 = 29
89-
let countOfXyber = handlerCount("/callback/25497");
90-
let countOfX25519 = handlerCount("/callback/29");
91-
let chan = makeChan(`https://${retryDomains[i]}:8443`);
92-
let [, buf] = await channelOpenPromise(chan, CL_ALLOW_UNKNOWN_CL);
93-
ok(buf);
94-
// The server will make a xyber768d00 callback for the initial request, and
95-
// then an x25519 callback for the retry. Both callback counts should
96-
// increment by one.
97-
equal(
98-
handlerCount("/callback/25497"),
99-
countOfXyber + 1,
100-
"negotiated xyber768d00"
101-
);
102-
equal(
103-
handlerCount("/callback/29"),
104-
countOfX25519 + 1,
105-
"negotiated x25519"
106-
);
107-
}
82+
// Get the number of xyber / x25519 callbacks prior to making the request
83+
// ssl_grp_kem_xyber768d00 = 25497
84+
// ssl_grp_ec_curve25519 = 29
85+
let countOfXyber = handlerCount("/callback/25497");
86+
let countOfX25519 = handlerCount("/callback/29");
87+
let chan = makeChan(`https://${retryDomain}:8443`);
88+
let [, buf] = await channelOpenPromise(chan, CL_ALLOW_UNKNOWN_CL);
89+
ok(buf);
90+
// The server will make a xyber768d00 callback for the initial request, and
91+
// then an x25519 callback for the retry. Both callback counts should
92+
// increment by one.
93+
equal(
94+
handlerCount("/callback/25497"),
95+
countOfXyber + 1,
96+
"negotiated xyber768d00"
97+
);
98+
equal(handlerCount("/callback/29"), countOfX25519 + 1, "negotiated x25519");
10899
if (!mozinfo.socketprocess_networking) {
109100
// Bug 1824574
110101
equal(
111102
1,
112103
await Glean.tls.xyberIntoleranceReason.PR_END_OF_FILE_ERROR.testGetValue(),
113104
"PR_END_OF_FILE_ERROR telemetry accumulated"
114105
);
115-
equal(
116-
1,
117-
await Glean.tls.xyberIntoleranceReason.SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE.testGetValue(),
118-
"SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE telemetry accumulated"
119-
);
120106
}
121107
}
122108
);
109+
110+
add_task(
111+
{
112+
skip_if: () => AppConstants.MOZ_SYSTEM_NSS,
113+
},
114+
async function testNoRetryXyber() {
115+
const retryDomain = "xyber-alert-after-server-hello.example.com";
116+
117+
Services.prefs.setBoolPref("security.tls.enable_kyber", true);
118+
Services.prefs.setCharPref("network.dns.localDomains", [retryDomain]);
119+
Services.prefs.setIntPref("network.http.speculative-parallel-limit", 0);
120+
121+
// Get the number of xyber / x25519 / p256 callbacks prior to making the request
122+
// ssl_grp_kem_xyber768d00 = 25497
123+
// ssl_grp_ec_curve25519 = 29
124+
let countOfXyber = handlerCount("/callback/25497");
125+
let countOfX25519 = handlerCount("/callback/29");
126+
let chan = makeChan(`https://${retryDomain}:8443`);
127+
let [req] = await channelOpenPromise(chan, CL_EXPECT_FAILURE);
128+
equal(req.status, 0x805a2f4d); // psm::GetXPCOMFromNSSError(SSL_ERROR_HANDSHAKE_FAILED)
129+
// The server will make a xyber768d00 callback for the initial request and
130+
// the client should not retry.
131+
equal(
132+
handlerCount("/callback/25497"),
133+
countOfXyber + 1,
134+
"negotiated xyber768d00"
135+
);
136+
equal(
137+
handlerCount("/callback/29"),
138+
countOfX25519,
139+
"did not negotiate x25519"
140+
);
141+
}
142+
);

security/manager/ssl/tests/unit/tlsserver/cmd/FaultyServer.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ const char* kHostZeroRttAlertUnexpected = "0rtt-alert-unexpected.example.com";
3939
const char* kHostZeroRttAlertDowngrade = "0rtt-alert-downgrade.example.com";
4040

4141
const char* kHostXyberNetInterrupt = "xyber-net-interrupt.example.com";
42-
const char* kHostXyberAlertUnexpected = "xyber-alert-unexpected.example.com";
42+
const char* kHostXyberAlertAfterServerHello =
43+
"xyber-alert-after-server-hello.example.com";
4344

4445
const char* kCertWildcard = "default-ee";
4546

@@ -55,7 +56,7 @@ const FaultyServerHost sFaultyServerHosts[]{
5556
{kHostZeroRttAlertUnexpected, kCertWildcard, ZeroRtt},
5657
{kHostZeroRttAlertDowngrade, kCertWildcard, ZeroRtt},
5758
{kHostXyberNetInterrupt, kCertWildcard, Xyber},
58-
{kHostXyberAlertUnexpected, kCertWildcard, Xyber},
59+
{kHostXyberAlertAfterServerHello, kCertWildcard, Xyber},
5960
{nullptr, nullptr},
6061
};
6162

@@ -199,8 +200,8 @@ void SecretCallbackFailXyber(PRFileDesc* fd, PRUint16 epoch,
199200
// The client will see this as a PR_END_OF_FILE / NS_ERROR_NET_INTERRUPT
200201
// error.
201202
ss->recordWriteCallback = FailingWriteCallback;
202-
} else if (!strcmp(host->mHostName, kHostXyberAlertUnexpected)) {
203-
SSL3_SendAlert(ss, alert_fatal, no_alert);
203+
} else if (!strcmp(host->mHostName, kHostXyberAlertAfterServerHello)) {
204+
SSL3_SendAlert(ss, alert_fatal, close_notify);
204205
}
205206
}
206207
}

0 commit comments

Comments
 (0)