summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Thomson <martin.thomson@gmail.com>2017-11-22 20:04:26 +1100
committerMartin Thomson <martin.thomson@gmail.com>2017-11-22 20:04:26 +1100
commit8395cf51212df6b224186a38d598479ad8ac8cf9 (patch)
treea30d726e7084e631cf8eee4c0ae29dabe57b3ac5
parent9350b5437e402600d336d4220e26a8f4b69bc493 (diff)
downloadnss-hg-8395cf51212df6b224186a38d598479ad8ac8cf9.tar.gz
Bug 1413787 - Fix record version numbers, r=franzikus
-rw-r--r--lib/ssl/ssl3con.c33
-rw-r--r--lib/ssl/sslspec.c33
2 files changed, 40 insertions, 26 deletions
diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
index 1e3dd870d..39295ef2d 100644
--- a/lib/ssl/ssl3con.c
+++ b/lib/ssl/ssl3con.c
@@ -4441,6 +4441,36 @@ ssl_MakeFakeSid(sslSocket *ss, PRUint8 *buf)
}
}
+/* Set the version fields of the cipher spec for a ClientHello. */
+static void
+ssl_SetClientHelloSpecVersion(sslSocket *ss, ssl3CipherSpec *spec)
+{
+ ssl_GetSpecWriteLock(ss);
+ PORT_Assert(spec->cipherDef->cipher == cipher_null);
+ /* This is - a best guess - but it doesn't matter here. */
+ spec->version = ss->vrange.max;
+ if (IS_DTLS(ss)) {
+ spec->recordVersion = SSL_LIBRARY_VERSION_DTLS_1_0_WIRE;
+ } else {
+ /* For new connections, cap the record layer version number of TLS
+ * ClientHello to { 3, 1 } (TLS 1.0). Some TLS 1.0 servers (which seem
+ * to use F5 BIG-IP) ignore ClientHello.client_version and use the
+ * record layer version number (TLSPlaintext.version) instead when
+ * negotiating protocol versions. In addition, if the record layer
+ * version number of ClientHello is { 3, 2 } (TLS 1.1) or higher, these
+ * servers reset the TCP connections. Lastly, some F5 BIG-IP servers
+ * hang if a record containing a ClientHello has a version greater than
+ * { 3, 1 } and a length greater than 255. Set this flag to work around
+ * such servers.
+ *
+ * The final version is set when a version is negotiated.
+ */
+ spec->recordVersion = PR_MIN(SSL_LIBRARY_VERSION_TLS_1_0,
+ ss->vrange.max);
+ }
+ ssl_ReleaseSpecWriteLock(ss);
+}
+
/* Called from ssl3_HandleHelloRequest(),
* ssl3_RedoHandshake()
* ssl_BeginClientHandshake (when resuming ssl3 session)
@@ -4494,6 +4524,9 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type)
ssl3_RestartHandshakeHashes(ss);
}
+ if (type == client_hello_initial) {
+ ssl_SetClientHelloSpecVersion(ss, ss->ssl3.cwSpec);
+ }
/* These must be reset every handshake. */
ssl3_ResetExtensionData(&ss->xtnData, ss);
ss->ssl3.hs.sendingSCSV = PR_FALSE;
diff --git a/lib/ssl/sslspec.c b/lib/ssl/sslspec.c
index 440ab0b99..4a251d08a 100644
--- a/lib/ssl/sslspec.c
+++ b/lib/ssl/sslspec.c
@@ -169,32 +169,13 @@ ssl_SetupNullCipherSpec(sslSocket *ss, CipherSpecDirection dir)
return SECFailure;
}
- /* The null spec is set before we start the handshake. So, we set the
- * version to the highest that is negotiated. Each version then follows its
- * own rules about construction of unencrypted records. For instance, TLS
- * 1.3 will set the record version number to TLS 1.0. */
- spec->version = ss->vrange.max;
- if (IS_DTLS(ss)) {
- spec->recordVersion = SSL_LIBRARY_VERSION_DTLS_1_0_WIRE;
- } else {
- /* For new connections, cap the record layer version number of TLS
- * ClientHello to { 3, 1 } (TLS 1.0). Some TLS 1.0 servers (which seem
- * to use F5 BIG-IP) ignore ClientHello.client_version and use the
- * record layer version number (TLSPlaintext.version) instead when
- * negotiating protocol versions. In addition, if the record layer
- * version number of ClientHello is { 3, 2 } (TLS 1.1) or higher, these
- * servers reset the TCP connections. Lastly, some F5 BIG-IP servers
- * hang if a record containing a ClientHello has a version greater than
- * { 3, 1 } and a length greater than 255. Set this flag to work around
- * such servers.
- *
- * We bump the version up when we settle on a version. Before producing
- * an initial ServerHello, or when processing it.
- */
- spec->recordVersion = PR_MIN(SSL_LIBRARY_VERSION_TLS_1_0,
- ss->vrange.max);
- }
-
+ /* Set default versions. This value will be used to generate and send
+ * alerts if a version is not negotiated. These values are overridden when
+ * sending a ClientHello and when a version is negotiated. */
+ spec->version = SSL_LIBRARY_VERSION_TLS_1_0;
+ spec->recordVersion = IS_DTLS(ss)
+ ? SSL_LIBRARY_VERSION_DTLS_1_0_WIRE
+ : SSL_LIBRARY_VERSION_TLS_1_0;
spec->cipherDef = &ssl_bulk_cipher_defs[cipher_null];
PORT_Assert(spec->cipherDef->cipher == cipher_null);
spec->macDef = &ssl_mac_defs[ssl_mac_null];