summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-24 19:04:12 +0000
committeragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-24 19:04:12 +0000
commitbf50b1b61803fb2478929941667a6f7ac34a5330 (patch)
tree64b35b103333e345401604982421c4622d5751db
parent699cab9ba3a0fcb9dd7f41a86cf008d34b96de1b (diff)
downloadchromium_src-bf50b1b61803fb2478929941667a6f7ac34a5330.zip
chromium_src-bf50b1b61803fb2478929941667a6f7ac34a5330.tar.gz
chromium_src-bf50b1b61803fb2478929941667a6f7ac34a5330.tar.bz2
SSL False Start Support
* Adds TLS false start support. This allows us to start sending encrypted data before we have validated the server's Finished message. (This behaviour is already enabled on Android.) I've verified that this works using netem to add a 200ms delay on the loopback adaptor. I've also checked that an incorrect Finished message from the server causes an error by hacking the Go TLS server. Beware when looking at packet traces that the time taken in NSS's SQLite calls can exceed the RTT of the connection and make it appear that this code isn't functioning. * Adds DEBUG and TRACE defines to libssl when building Chromium in Debug mode. This means that setting SSLTRACE in the environment now works for debug builds. http://codereview.chromium.org/518065 BUG=none TEST=none git-svn-id: svn://svn.chromium.org/chrome/trunk/src@39905 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--net/socket/ssl_client_socket_nss.cc6
-rw-r--r--net/third_party/nss/README.google3
-rw-r--r--net/third_party/nss/nss.gyp7
-rw-r--r--net/third_party/nss/patches/falsestart.patch319
-rw-r--r--net/third_party/nss/ssl/ssl.h11
-rw-r--r--net/third_party/nss/ssl/ssl3con.c20
-rw-r--r--net/third_party/nss/ssl/ssl3gthr.c13
-rw-r--r--net/third_party/nss/ssl/sslimpl.h3
-rw-r--r--net/third_party/nss/ssl/sslsecur.c6
-rw-r--r--net/third_party/nss/ssl/sslsock.c11
10 files changed, 396 insertions, 3 deletions
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
index 2c703d6..d1d0054 100644
--- a/net/socket/ssl_client_socket_nss.cc
+++ b/net/socket/ssl_client_socket_nss.cc
@@ -380,6 +380,12 @@ int SSLClientSocketNSS::InitializeSSLOptions() {
LOG(INFO) << "SSL_ENABLE_DEFLATE failed. Old system nss?";
#endif
+#ifdef SSL_ENABLE_FALSE_START
+ rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_FALSE_START, PR_TRUE);
+ if (rv != SECSuccess)
+ LOG(INFO) << "SSL_ENABLE_FALSE_START failed. Old system nss?";
+#endif
+
#ifdef SSL_ENABLE_RENEGOTIATION
// We allow servers to request renegotiation. Since we're a client,
// prohibiting this is rather a waste of time. Only servers are in a position
diff --git a/net/third_party/nss/README.google b/net/third_party/nss/README.google
index ce46e1a..291e176 100644
--- a/net/third_party/nss/README.google
+++ b/net/third_party/nss/README.google
@@ -9,6 +9,9 @@ Patches:
patches/nextproto.patch
http://codereview.chromium.org/415005
+ * False start support
+ patches/falsestart.patch
+
* Commenting out a couple of functions because they need NSS symbols
which may not exist in the system NSS library.
patches/versionskew.patch
diff --git a/net/third_party/nss/nss.gyp b/net/third_party/nss/nss.gyp
index 5511066..1e7ef49 100644
--- a/net/third_party/nss/nss.gyp
+++ b/net/third_party/nss/nss.gyp
@@ -126,6 +126,13 @@
},
}],
],
+ 'configurations': {
+ 'Debug_Base': {
+ 'defines': [
+ 'DEBUG',
+ ],
+ },
+ },
},
],
}
diff --git a/net/third_party/nss/patches/falsestart.patch b/net/third_party/nss/patches/falsestart.patch
new file mode 100644
index 0000000..ad41b20e
--- /dev/null
+++ b/net/third_party/nss/patches/falsestart.patch
@@ -0,0 +1,319 @@
+diff --git a/mozilla/security/nss/cmd/strsclnt/strsclnt.c b/mozilla/security/nss/cmd/strsclnt/strsclnt.c
+index c266644..1f71434 100644
+--- a/mozilla/security/nss/cmd/strsclnt/strsclnt.c
++++ b/mozilla/security/nss/cmd/strsclnt/strsclnt.c
+@@ -162,6 +162,7 @@ static PRBool disableLocking = PR_FALSE;
+ static PRBool ignoreErrors = PR_FALSE;
+ static PRBool enableSessionTickets = PR_FALSE;
+ static PRBool enableCompression = PR_FALSE;
++static PRBool enableFalseStart = PR_FALSE;
+
+ PRIntervalTime maxInterval = PR_INTERVAL_NO_TIMEOUT;
+
+@@ -197,7 +198,8 @@ Usage(const char *progName)
+ " -U means enable throttling up threads\n"
+ " -B bypasses the PKCS11 layer for SSL encryption and MACing\n"
+ " -u enable TLS Session Ticket extension\n"
+- " -z enable compression\n",
++ " -z enable compression\n"
++ " -g enable false start\n",
+ progName);
+ exit(1);
+ }
+@@ -1244,6 +1246,12 @@ client_main(
+ errExit("SSL_OptionSet SSL_ENABLE_DEFLATE");
+ }
+
++ if (enableFalseStart) {
++ rv = SSL_OptionSet(model_sock, SSL_ENABLE_FALSE_START, PR_TRUE);
++ if (rv != SECSuccess)
++ errExit("SSL_OptionSet SSL_ENABLE_FALSE_START");
++ }
++
+ SSL_SetURL(model_sock, hostName);
+
+ SSL_AuthCertificateHook(model_sock, mySSLAuthCertificate,
+@@ -1354,7 +1362,7 @@ main(int argc, char **argv)
+
+
+ optstate = PL_CreateOptState(argc, argv,
+- "23BC:DNP:TUW:a:c:d:f:in:op:qst:uvw:z");
++ "23BC:DNP:TUW:a:c:d:f:gin:op:qst:uvw:z");
+ while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch(optstate->option) {
+
+@@ -1384,6 +1392,8 @@ main(int argc, char **argv)
+
+ case 'f': fileName = optstate->value; break;
+
++ case 'g': enableFalseStart = PR_TRUE; break;
++
+ case 'i': ignoreErrors = PR_TRUE; break;
+
+ case 'n': nickName = PL_strdup(optstate->value); break;
+diff --git a/mozilla/security/nss/cmd/tstclnt/tstclnt.c b/mozilla/security/nss/cmd/tstclnt/tstclnt.c
+index c15a0ad..55684e6 100644
+--- a/mozilla/security/nss/cmd/tstclnt/tstclnt.c
++++ b/mozilla/security/nss/cmd/tstclnt/tstclnt.c
+@@ -225,6 +225,7 @@ static void Usage(const char *progName)
+ fprintf(stderr, "%-20s Renegotiate N times (resuming session if N>1).\n", "-r N");
+ fprintf(stderr, "%-20s Enable the session ticket extension.\n", "-u");
+ fprintf(stderr, "%-20s Enable compression.\n", "-z");
++ fprintf(stderr, "%-20s Enable false start.\n", "-g");
+ fprintf(stderr, "%-20s Letter(s) chosen from the following list\n",
+ "-c ciphers");
+ fprintf(stderr,
+@@ -521,6 +522,7 @@ int main(int argc, char **argv)
+ int useExportPolicy = 0;
+ int enableSessionTickets = 0;
+ int enableCompression = 0;
++ int enableFalseStart = 0;
+ PRSocketOptionData opt;
+ PRNetAddr addr;
+ PRPollDesc pollset[2];
+@@ -551,7 +553,7 @@ int main(int argc, char **argv)
+ }
+
+ optstate = PL_CreateOptState(argc, argv,
+- "23BSTW:a:c:d:fh:m:n:op:qr:suvw:xz");
++ "23BSTW:a:c:d:fgh:m:n:op:qr:suvw:xz");
+ while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
+ switch (optstate->option) {
+ case '?':
+@@ -578,6 +580,8 @@ int main(int argc, char **argv)
+
+ case 'c': cipherString = PORT_Strdup(optstate->value); break;
+
++ case 'g': enableFalseStart = 1; break;
++
+ case 'd': certDir = PORT_Strdup(optstate->value); break;
+
+ case 'f': clientSpeaksFirst = PR_TRUE; break;
+@@ -863,7 +867,14 @@ int main(int argc, char **argv)
+ SECU_PrintError(progName, "error enabling compression");
+ return 1;
+ }
+-
++
++ /* enable false start. */
++ rv = SSL_OptionSet(s, SSL_ENABLE_FALSE_START, enableFalseStart);
++ if (rv != SECSuccess) {
++ SECU_PrintError(progName, "error enabling false start");
++ return 1;
++ }
++
+ SSL_SetPKCS11PinArg(s, &pwdata);
+
+ SSL_AuthCertificateHook(s, SSL_AuthCertificate, (void *)handle);
+diff --git a/mozilla/security/nss/lib/ssl/ssl.h b/mozilla/security/nss/lib/ssl/ssl.h
+index e285ab4..bd1bfd3 100644
+--- a/mozilla/security/nss/lib/ssl/ssl.h
++++ b/mozilla/security/nss/lib/ssl/ssl.h
+@@ -128,6 +128,17 @@ SSL_IMPORT PRFileDesc *SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd);
+ /* Renegotiation Info (RI) */
+ /* extension in ALL handshakes. */
+ /* default: off */
++#define SSL_ENABLE_FALSE_START 22 /* Enable SSL false start (off by */
++ /* default, applies only to */
++ /* clients). False start is a */
++/* mode where an SSL client will start sending application data before */
++/* verifying the server's Finished message. This means that we could end up */
++/* sending data to an imposter. However, the data will be encrypted and */
++/* only the true server can derive the session key. Thus, so long as the */
++/* cipher isn't broken this is safe. Because of this, False Start will only */
++/* occur on RSA or DH ciphersuites where the cipher's key length is >= 80 */
++/* bits. The advantage of False Start is that it saves a round trip for */
++/* client-speaks-first protocols when performing a full handshake. */
+
+ #ifdef SSL_DEPRECATED_FUNCTION
+ /* Old deprecated function names */
+diff --git a/mozilla/security/nss/lib/ssl/ssl3con.c b/mozilla/security/nss/lib/ssl/ssl3con.c
+index 6b37c4f..f073431 100644
+--- a/mozilla/security/nss/lib/ssl/ssl3con.c
++++ b/mozilla/security/nss/lib/ssl/ssl3con.c
+@@ -5656,7 +5656,17 @@ ssl3_RestartHandshakeAfterCertReq(sslSocket * ss,
+ return rv;
+ }
+
+-
++PRBool
++ssl3_CanFalseStart(sslSocket *ss) {
++ return ss->opt.enableFalseStart &&
++ !ss->sec.isServer &&
++ !ss->ssl3.hs.isResuming &&
++ ss->ssl3.cwSpec &&
++ ss->ssl3.cwSpec->cipher_def->secret_key_size >= 10 &&
++ (ss->ssl3.hs.kea_def->exchKeyType == ssl_kea_rsa ||
++ ss->ssl3.hs.kea_def->exchKeyType == ssl_kea_dh ||
++ ss->ssl3.hs.kea_def->exchKeyType == ssl_kea_ecdh);
++}
+
+ /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
+ * ssl3 Server Hello Done message.
+@@ -5728,6 +5738,12 @@ ssl3_HandleServerHelloDone(sslSocket *ss)
+ ss->ssl3.hs.ws = wait_new_session_ticket;
+ else
+ ss->ssl3.hs.ws = wait_change_cipher;
++
++ /* Do the handshake callback for sslv3 here. */
++ if (ss->handshakeCallback != NULL && ssl3_CanFalseStart(ss)) {
++ (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
++ }
++
+ return SECSuccess;
+
+ loser:
+@@ -8468,7 +8484,7 @@ xmit_loser:
+ ss->ssl3.hs.ws = idle_handshake;
+
+ /* Do the handshake callback for sslv3 here. */
+- if (ss->handshakeCallback != NULL) {
++ if (ss->handshakeCallback != NULL && !ssl3_CanFalseStart(ss)) {
+ (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
+ }
+
+diff --git a/mozilla/security/nss/lib/ssl/ssl3gthr.c b/mozilla/security/nss/lib/ssl/ssl3gthr.c
+index bdd2958..28fe154 100644
+--- a/mozilla/security/nss/lib/ssl/ssl3gthr.c
++++ b/mozilla/security/nss/lib/ssl/ssl3gthr.c
+@@ -188,6 +188,7 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
+ {
+ SSL3Ciphertext cText;
+ int rv;
++ PRBool canFalseStart = PR_FALSE;
+
+ PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
+ do {
+@@ -207,7 +208,17 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
+ if (rv < 0) {
+ return ss->recvdCloseNotify ? 0 : rv;
+ }
+- } while (ss->ssl3.hs.ws != idle_handshake && ss->gs.buf.len == 0);
++
++ if (ss->opt.enableFalseStart) {
++ ssl_GetSSL3HandshakeLock(ss);
++ canFalseStart = (ss->ssl3.hs.ws == wait_change_cipher ||
++ ss->ssl3.hs.ws == wait_new_session_ticket) &&
++ ssl3_CanFalseStart(ss);
++ ssl_ReleaseSSL3HandshakeLock(ss);
++ }
++ } while (ss->ssl3.hs.ws != idle_handshake &&
++ !canFalseStart &&
++ ss->gs.buf.len == 0);
+
+ ss->gs.readOffset = 0;
+ ss->gs.writeOffset = ss->gs.buf.len;
+diff --git a/mozilla/security/nss/lib/ssl/sslimpl.h b/mozilla/security/nss/lib/ssl/sslimpl.h
+index 7581b98..00f0ce2 100644
+--- a/mozilla/security/nss/lib/ssl/sslimpl.h
++++ b/mozilla/security/nss/lib/ssl/sslimpl.h
+@@ -333,6 +333,7 @@ typedef struct sslOptionsStr {
+ unsigned int enableDeflate : 1; /* 19 */
+ unsigned int enableRenegotiation : 2; /* 20-21 */
+ unsigned int requireSafeNegotiation : 1; /* 22 */
++ unsigned int enableFalseStart : 1; /* 23 */
+ } sslOptions;
+
+ typedef enum { sslHandshakingUndetermined = 0,
+@@ -1250,6 +1251,8 @@ extern void ssl_SetAlwaysBlock(sslSocket *ss);
+
+ extern SECStatus ssl_EnableNagleDelay(sslSocket *ss, PRBool enabled);
+
++extern PRBool ssl3_CanFalseStart(sslSocket *ss);
++
+ #define SSL_LOCK_READER(ss) if (ss->recvLock) PZ_Lock(ss->recvLock)
+ #define SSL_UNLOCK_READER(ss) if (ss->recvLock) PZ_Unlock(ss->recvLock)
+ #define SSL_LOCK_WRITER(ss) if (ss->sendLock) PZ_Lock(ss->sendLock)
+diff --git a/mozilla/security/nss/lib/ssl/sslsecur.c b/mozilla/security/nss/lib/ssl/sslsecur.c
+index 8f79135..4dc0475 100644
+--- a/mozilla/security/nss/lib/ssl/sslsecur.c
++++ b/mozilla/security/nss/lib/ssl/sslsecur.c
+@@ -148,6 +148,12 @@ ssl_Do1stHandshake(sslSocket *ss)
+ ss->gs.readOffset = 0;
+ break;
+ }
++ if (ss->version >= SSL_LIBRARY_VERSION_3_0 &&
++ (ss->ssl3.hs.ws == wait_change_cipher ||
++ ss->ssl3.hs.ws == wait_new_session_ticket) &&
++ ssl3_CanFalseStart(ss)) {
++ break;
++ }
+ rv = (*ss->handshake)(ss);
+ ++loopCount;
+ /* This code must continue to loop on SECWouldBlock,
+diff --git a/mozilla/security/nss/lib/ssl/sslsock.c b/mozilla/security/nss/lib/ssl/sslsock.c
+index aab48d6..40f633a 100644
+--- a/mozilla/security/nss/lib/ssl/sslsock.c
++++ b/mozilla/security/nss/lib/ssl/sslsock.c
+@@ -183,6 +183,7 @@ static sslOptions ssl_defaults = {
+ PR_FALSE, /* enableDeflate */
+ 2, /* enableRenegotiation (default: requires extension) */
+ PR_FALSE, /* requireSafeNegotiation */
++ PR_FALSE, /* enableFalseStart */
+ };
+
+ sslSessionIDLookupFunc ssl_sid_lookup;
+@@ -728,6 +729,10 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on)
+ ss->opt.requireSafeNegotiation = on;
+ break;
+
++ case SSL_ENABLE_FALSE_START:
++ ss->opt.enableFalseStart = on;
++ break;
++
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ rv = SECFailure;
+@@ -791,6 +796,7 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn)
+ on = ss->opt.enableRenegotiation; break;
+ case SSL_REQUIRE_SAFE_NEGOTIATION:
+ on = ss->opt.requireSafeNegotiation; break;
++ case SSL_ENABLE_FALSE_START: on = ss->opt.enableFalseStart; break;
+
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+@@ -841,6 +847,7 @@ SSL_OptionGetDefault(PRInt32 which, PRBool *pOn)
+ case SSL_REQUIRE_SAFE_NEGOTIATION:
+ on = ssl_defaults.requireSafeNegotiation;
+ break;
++ case SSL_ENABLE_FALSE_START: on = ssl_defaults.enableFalseStart; break;
+
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+@@ -984,6 +991,10 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on)
+ ssl_defaults.requireSafeNegotiation = on;
+ break;
+
++ case SSL_ENABLE_FALSE_START:
++ ssl_defaults.enableFalseStart = on;
++ break;
++
+ default:
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+diff --git a/mozilla/security/nss/tests/ssl/sslstress.txt b/mozilla/security/nss/tests/ssl/sslstress.txt
+index 9a3aae8..c2a5c76 100644
+--- a/mozilla/security/nss/tests/ssl/sslstress.txt
++++ b/mozilla/security/nss/tests/ssl/sslstress.txt
+@@ -42,9 +42,11 @@
+ noECC 0 _ -c_1000_-C_A Stress SSL2 RC4 128 with MD5
+ noECC 0 _ -c_1000_-C_c_-T Stress SSL3 RC4 128 with MD5
+ noECC 0 _ -c_1000_-C_c Stress TLS RC4 128 with MD5
++ noECC 0 _ -c_1000_-C_c_-h Stress TLS RC4 128 with MD5 (false start)
+ noECC 0 -u -2_-c_1000_-C_c_-u Stress TLS RC4 128 with MD5 (session ticket)
+ noECC 0 -z -2_-c_1000_-C_c_-z Stress TLS RC4 128 with MD5 (compression)
+ noECC 0 -u_-z -2_-c_1000_-C_c_-u_-z Stress TLS RC4 128 with MD5 (session ticket, compression)
++ noECC 0 -u_-z -2_-c_1000_-C_c_-u_-z_-h Stress TLS RC4 128 with MD5 (session ticket, compression, false start)
+ SNI 0 -u_-a_Host-sni.Dom -2_-3_-c_1000_-C_c_-u Stress TLS RC4 128 with MD5 (session ticket, SNI)
+
+ #
+@@ -55,7 +57,9 @@
+ noECC 0 -r_-r -c_100_-C_c_-N_-n_TestUser Stress TLS RC4 128 with MD5 (no reuse, client auth)
+ noECC 0 -r_-r_-u -2_-c_100_-C_c_-n_TestUser_-u Stress TLS RC4 128 with MD5 (session ticket, client auth)
+ noECC 0 -r_-r_-z -2_-c_100_-C_c_-n_TestUser_-z Stress TLS RC4 128 with MD5 (compression, client auth)
++ noECC 0 -r_-r_-z -2_-c_100_-C_c_-n_TestUser_-z_-h Stress TLS RC4 128 with MD5 (compression, client auth, false start)
+ noECC 0 -r_-r_-u_-z -2_-c_100_-C_c_-n_TestUser_-u_-z Stress TLS RC4 128 with MD5 (session ticket, compression, client auth)
++ noECC 0 -r_-r_-u_-z -2_-c_100_-C_c_-n_TestUser_-u_-z_-h Stress TLS RC4 128 with MD5 (session ticket, compression, client auth, false start)
+ SNI 0 -r_-r_-u_-a_Host-sni.Dom -2_-3_-c_1000_-C_c_-u Stress TLS RC4 128 with MD5 (session ticket, SNI, client auth, default virt host)
+ SNI 0 -r_-r_-u_-a_Host-sni.Dom_-k_Host-sni.Dom -2_-3_-c_1000_-C_c_-u_-a_Host-sni.Dom Stress TLS RC4 128 with MD5 (session ticket, SNI, client auth, change virt host)
+
diff --git a/net/third_party/nss/ssl/ssl.h b/net/third_party/nss/ssl/ssl.h
index b0e77df..0bc02f8 100644
--- a/net/third_party/nss/ssl/ssl.h
+++ b/net/third_party/nss/ssl/ssl.h
@@ -128,6 +128,17 @@ SSL_IMPORT PRFileDesc *SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd);
/* Renegotiation Info (RI) */
/* extension in ALL handshakes. */
/* default: off */
+#define SSL_ENABLE_FALSE_START 22 /* Enable SSL false start (off by */
+ /* default, applies only to */
+ /* clients). False start is a */
+/* mode where an SSL client will start sending application data before */
+/* verifying the server's Finished message. This means that we could end up */
+/* sending data to an imposter. However, the data will be encrypted and */
+/* only the true server can derive the session key. Thus, so long as the */
+/* cipher isn't broken this is safe. Because of this, False Start will only */
+/* occur on RSA or DH ciphersuites where the cipher's key length is >= 80 */
+/* bits. The advantage of False Start is that it saves a round trip for */
+/* client-speaks-first protocols when performing a full handshake. */
#ifdef SSL_DEPRECATED_FUNCTION
/* Old deprecated function names */
diff --git a/net/third_party/nss/ssl/ssl3con.c b/net/third_party/nss/ssl/ssl3con.c
index 545e51e..24dc01c 100644
--- a/net/third_party/nss/ssl/ssl3con.c
+++ b/net/third_party/nss/ssl/ssl3con.c
@@ -5657,7 +5657,17 @@ ssl3_RestartHandshakeAfterCertReq(sslSocket * ss,
return rv;
}
-
+PRBool
+ssl3_CanFalseStart(sslSocket *ss) {
+ return ss->opt.enableFalseStart &&
+ !ss->sec.isServer &&
+ !ss->ssl3.hs.isResuming &&
+ ss->ssl3.cwSpec &&
+ ss->ssl3.cwSpec->cipher_def->secret_key_size >= 10 &&
+ (ss->ssl3.hs.kea_def->exchKeyType == ssl_kea_rsa ||
+ ss->ssl3.hs.kea_def->exchKeyType == ssl_kea_dh ||
+ ss->ssl3.hs.kea_def->exchKeyType == ssl_kea_ecdh);
+}
/* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
* ssl3 Server Hello Done message.
@@ -5735,6 +5745,12 @@ ssl3_HandleServerHelloDone(sslSocket *ss)
ss->ssl3.hs.ws = wait_new_session_ticket;
else
ss->ssl3.hs.ws = wait_change_cipher;
+
+ /* Do the handshake callback for sslv3 here. */
+ if (ss->handshakeCallback != NULL && ssl3_CanFalseStart(ss)) {
+ (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
+ }
+
return SECSuccess;
loser:
@@ -8509,7 +8525,7 @@ xmit_loser:
ss->ssl3.hs.ws = idle_handshake;
/* Do the handshake callback for sslv3 here. */
- if (ss->handshakeCallback != NULL) {
+ if (ss->handshakeCallback != NULL && !ssl3_CanFalseStart(ss)) {
(ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
}
diff --git a/net/third_party/nss/ssl/ssl3gthr.c b/net/third_party/nss/ssl/ssl3gthr.c
index bdd2958..28fe154 100644
--- a/net/third_party/nss/ssl/ssl3gthr.c
+++ b/net/third_party/nss/ssl/ssl3gthr.c
@@ -188,6 +188,7 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
{
SSL3Ciphertext cText;
int rv;
+ PRBool canFalseStart = PR_FALSE;
PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
do {
@@ -207,7 +208,17 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
if (rv < 0) {
return ss->recvdCloseNotify ? 0 : rv;
}
- } while (ss->ssl3.hs.ws != idle_handshake && ss->gs.buf.len == 0);
+
+ if (ss->opt.enableFalseStart) {
+ ssl_GetSSL3HandshakeLock(ss);
+ canFalseStart = (ss->ssl3.hs.ws == wait_change_cipher ||
+ ss->ssl3.hs.ws == wait_new_session_ticket) &&
+ ssl3_CanFalseStart(ss);
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ }
+ } while (ss->ssl3.hs.ws != idle_handshake &&
+ !canFalseStart &&
+ ss->gs.buf.len == 0);
ss->gs.readOffset = 0;
ss->gs.writeOffset = ss->gs.buf.len;
diff --git a/net/third_party/nss/ssl/sslimpl.h b/net/third_party/nss/ssl/sslimpl.h
index 0658d2c..a800d56 100644
--- a/net/third_party/nss/ssl/sslimpl.h
+++ b/net/third_party/nss/ssl/sslimpl.h
@@ -338,6 +338,7 @@ typedef struct sslOptionsStr {
unsigned int enableDeflate : 1; /* 19 */
unsigned int enableRenegotiation : 2; /* 20-21 */
unsigned int requireSafeNegotiation : 1; /* 22 */
+ unsigned int enableFalseStart : 1; /* 23 */
} sslOptions;
typedef enum { sslHandshakingUndetermined = 0,
@@ -1266,6 +1267,8 @@ extern void ssl_SetAlwaysBlock(sslSocket *ss);
extern SECStatus ssl_EnableNagleDelay(sslSocket *ss, PRBool enabled);
+extern PRBool ssl3_CanFalseStart(sslSocket *ss);
+
#define SSL_LOCK_READER(ss) if (ss->recvLock) PZ_Lock(ss->recvLock)
#define SSL_UNLOCK_READER(ss) if (ss->recvLock) PZ_Unlock(ss->recvLock)
#define SSL_LOCK_WRITER(ss) if (ss->sendLock) PZ_Lock(ss->sendLock)
diff --git a/net/third_party/nss/ssl/sslsecur.c b/net/third_party/nss/ssl/sslsecur.c
index 80c2ba6..a8184478 100644
--- a/net/third_party/nss/ssl/sslsecur.c
+++ b/net/third_party/nss/ssl/sslsecur.c
@@ -148,6 +148,12 @@ ssl_Do1stHandshake(sslSocket *ss)
ss->gs.readOffset = 0;
break;
}
+ if (ss->version >= SSL_LIBRARY_VERSION_3_0 &&
+ (ss->ssl3.hs.ws == wait_change_cipher ||
+ ss->ssl3.hs.ws == wait_new_session_ticket) &&
+ ssl3_CanFalseStart(ss)) {
+ break;
+ }
rv = (*ss->handshake)(ss);
++loopCount;
/* This code must continue to loop on SECWouldBlock,
diff --git a/net/third_party/nss/ssl/sslsock.c b/net/third_party/nss/ssl/sslsock.c
index 722fe60..c4611a0 100644
--- a/net/third_party/nss/ssl/sslsock.c
+++ b/net/third_party/nss/ssl/sslsock.c
@@ -184,6 +184,7 @@ static sslOptions ssl_defaults = {
PR_FALSE, /* enableDeflate */
2, /* enableRenegotiation (default: requires extension) */
PR_FALSE, /* requireSafeNegotiation */
+ PR_FALSE, /* enableFalseStart */
};
sslSessionIDLookupFunc ssl_sid_lookup;
@@ -733,6 +734,10 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on)
ss->opt.requireSafeNegotiation = on;
break;
+ case SSL_ENABLE_FALSE_START:
+ ss->opt.enableFalseStart = on;
+ break;
+
default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure;
@@ -796,6 +801,7 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn)
on = ss->opt.enableRenegotiation; break;
case SSL_REQUIRE_SAFE_NEGOTIATION:
on = ss->opt.requireSafeNegotiation; break;
+ case SSL_ENABLE_FALSE_START: on = ss->opt.enableFalseStart; break;
default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
@@ -846,6 +852,7 @@ SSL_OptionGetDefault(PRInt32 which, PRBool *pOn)
case SSL_REQUIRE_SAFE_NEGOTIATION:
on = ssl_defaults.requireSafeNegotiation;
break;
+ case SSL_ENABLE_FALSE_START: on = ssl_defaults.enableFalseStart; break;
default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
@@ -989,6 +996,10 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on)
ssl_defaults.requireSafeNegotiation = on;
break;
+ case SSL_ENABLE_FALSE_START:
+ ssl_defaults.enableFalseStart = on;
+ break;
+
default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;