Detect WatchGuard's TLS 1.3 interference failure mode.
WatchGuard's bug is very distinctive. Report a dedicated error code out
of BoringSSL so we can better track this.
Bug: chromium:733223
Change-Id: Ia42abd8654e7987b1d43c63a4f454f35f6aa873b
Reviewed-on: https://boringssl-review.googlesource.com/17328
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/crypto/err/ssl.errordata b/crypto/err/ssl.errordata
index 641d873..7949cc7 100644
--- a/crypto/err/ssl.errordata
+++ b/crypto/err/ssl.errordata
@@ -1,4 +1,5 @@
SSL,277,ALPN_MISMATCH_ON_EARLY_DATA
+SSL,281,APPLICATION_DATA_INSTEAD_OF_HANDSHAKE
SSL,100,APP_DATA_IN_HANDSHAKE
SSL,101,ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT
SSL,102,BAD_ALERT
@@ -178,6 +179,7 @@
SSL,219,TOO_MANY_EMPTY_FRAGMENTS
SSL,260,TOO_MANY_KEY_UPDATES
SSL,220,TOO_MANY_WARNING_ALERTS
+SSL,1117,TOO_MUCH_READ_EARLY_DATA
SSL,270,TOO_MUCH_SKIPPED_EARLY_DATA
SSL,221,UNABLE_TO_FIND_ECDH_PARAMETERS
SSL,222,UNEXPECTED_EXTENSION
@@ -210,4 +212,3 @@
SSL,278,WRONG_VERSION_ON_EARLY_DATA
SSL,248,X509_LIB
SSL,249,X509_VERIFICATION_SETUP_PROBLEMS
-SSL,1117,TOO_MUCH_READ_EARLY_DATA
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 295f381..b5f1c57 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -4678,6 +4678,7 @@
#define SSL_R_WRONG_VERSION_ON_EARLY_DATA 278
#define SSL_R_CHANNEL_ID_ON_EARLY_DATA 279
#define SSL_R_NO_SUPPORTED_VERSIONS_ENABLED 280
+#define SSL_R_APPLICATION_DATA_INSTEAD_OF_HANDSHAKE 281
#define SSL_R_SSLV3_ALERT_CLOSE_NOTIFY 1000
#define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010
#define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020
diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c
index b624135..445f882 100644
--- a/ssl/s3_pkt.c
+++ b/ssl/s3_pkt.c
@@ -511,6 +511,17 @@
}
}
+ /* WatchGuard's TLS 1.3 interference bug is very distinctive: they drop the
+ * ServerHello and send the remaining encrypted application data records
+ * as-is. This manifests as an application data record when we expect
+ * handshake. Report a dedicated error code for this case. */
+ if (!ssl->server && rr->type == SSL3_RT_APPLICATION_DATA &&
+ ssl->s3->aead_read_ctx == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_APPLICATION_DATA_INSTEAD_OF_HANDSHAKE);
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+ return -1;
+ }
+
if (rr->type != SSL3_RT_HANDSHAKE) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 62e0056..d9218f2 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -1577,7 +1577,7 @@
},
},
shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
+ expectedError: ":APPLICATION_DATA_INSTEAD_OF_HANDSHAKE:",
},
{
name: "AppDataBeforeHandshake-Empty",
@@ -1587,7 +1587,7 @@
},
},
shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
+ expectedError: ":APPLICATION_DATA_INSTEAD_OF_HANDSHAKE:",
},
{
protocol: dtls,
@@ -1757,7 +1757,7 @@
},
shimWritesFirst: true,
shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
+ expectedError: ":APPLICATION_DATA_INSTEAD_OF_HANDSHAKE:",
},
{
name: "FalseStart-SkipServerSecondLeg-Implicit",
@@ -1778,7 +1778,7 @@
"-advertise-alpn", "\x03foo",
},
shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
+ expectedError: ":APPLICATION_DATA_INSTEAD_OF_HANDSHAKE:",
},
{
testType: serverTest,