nss: CVE-2013-1740
the patch comes from: http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-1740 https://bugzilla.mozilla.org/show_bug.cgi?id=919877 https://bugzilla.mozilla.org/show_bug.cgi?id=713933 changeset: 10946:f28426e944ae user: Wan-Teh Chang <wtc@google.com> date: Tue Nov 26 16:44:39 2013 -0800 summary: Bug 713933: Handle the return value of both ssl3_HandleRecord calls changeset: 10945:774c7dec7565 user: Wan-Teh Chang <wtc@google.com> date: Mon Nov 25 19:16:23 2013 -0800 summary: Bug 713933: Declare the |falseStart| local variable in the smallest changeset: 10848:141fae8fb2e8 user: Wan-Teh Chang <wtc@google.com> date: Mon Sep 23 11:25:41 2013 -0700 summary: Bug 681839: Allow SSL_HandshakeNegotiatedExtension to be called before the handshake is finished, r=brian@briansmith.org changeset: 10898:1b9c43d28713 user: Brian Smith <brian@briansmith.org> date: Thu Oct 31 15:40:42 2013 -0700 summary: Bug 713933: Make SSL False Start work with asynchronous certificate validation, r=wtc (From OE-Core rev: 11e728e64e37eec72ed0cb3fb4d5a49ddeb88666) Signed-off-by: Li Wang <li.wang@windriver.com> Signed-off-by: Roy Li <rongqing.li@windriver.com> Signed-off-by: Saul Wold <sgw@linux.intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
parent
64f817458a
commit
058ce93c7e
|
@ -0,0 +1,916 @@
|
|||
nss: CVE-2013-1740
|
||||
|
||||
Upstream-Status: Backport
|
||||
|
||||
the patch comes from:
|
||||
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-1740
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=919877
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=713933
|
||||
|
||||
changeset: 10946:f28426e944ae
|
||||
user: Wan-Teh Chang <wtc@google.com>
|
||||
date: Tue Nov 26 16:44:39 2013 -0800
|
||||
summary: Bug 713933: Handle the return value of both ssl3_HandleRecord calls
|
||||
|
||||
changeset: 10945:774c7dec7565
|
||||
user: Wan-Teh Chang <wtc@google.com>
|
||||
date: Mon Nov 25 19:16:23 2013 -0800
|
||||
summary: Bug 713933: Declare the |falseStart| local variable in the smallest
|
||||
|
||||
changeset: 10848:141fae8fb2e8
|
||||
user: Wan-Teh Chang <wtc@google.com>
|
||||
date: Mon Sep 23 11:25:41 2013 -0700
|
||||
summary: Bug 681839: Allow SSL_HandshakeNegotiatedExtension to be called before the handshake is finished, r=brian@briansmith.org
|
||||
|
||||
changeset: 10898:1b9c43d28713
|
||||
user: Brian Smith <brian@briansmith.org>
|
||||
date: Thu Oct 31 15:40:42 2013 -0700
|
||||
summary: Bug 713933: Make SSL False Start work with asynchronous certificate validation, r=wtc
|
||||
|
||||
Signed-off-by: Li Wang <li.wang@windriver.com>
|
||||
---
|
||||
nss/lib/ssl/ssl.def | 7 ++
|
||||
nss/lib/ssl/ssl.h | 54 +++++++++++---
|
||||
nss/lib/ssl/ssl3con.c | 188 +++++++++++++++++++++++++++++++++++------------
|
||||
nss/lib/ssl/ssl3gthr.c | 63 ++++++++++++----
|
||||
nss/lib/ssl/sslauth.c | 10 +--
|
||||
nss/lib/ssl/sslimpl.h | 22 +++++-
|
||||
nss/lib/ssl/sslinfo.c | 10 +--
|
||||
nss/lib/ssl/sslreveal.c | 9 +--
|
||||
nss/lib/ssl/sslsecur.c | 139 ++++++++++++++++++++++++++++-------
|
||||
nss/lib/ssl/sslsock.c | 12 ++-
|
||||
10 files changed, 386 insertions(+), 128 deletions(-)
|
||||
|
||||
diff --git a/nss/lib/ssl/ssl.def b/nss/lib/ssl/ssl.def
|
||||
index fbf7fc5..e937bd4 100644
|
||||
--- a/nss/lib/ssl/ssl.def
|
||||
+++ b/nss/lib/ssl/ssl.def
|
||||
@@ -163,3 +163,10 @@ SSL_SetStapledOCSPResponses;
|
||||
;+ local:
|
||||
;+*;
|
||||
;+};
|
||||
+;+NSS_3.15.3 { # NSS 3.15.3 release
|
||||
+;+ global:
|
||||
+SSL_RecommendedCanFalseStart;
|
||||
+SSL_SetCanFalseStartCallback;
|
||||
+;+ local:
|
||||
+;+*;
|
||||
+;+};
|
||||
diff --git a/nss/lib/ssl/ssl.h b/nss/lib/ssl/ssl.h
|
||||
index 6db0e34..ddeaaef 100644
|
||||
--- a/nss/lib/ssl/ssl.h
|
||||
+++ b/nss/lib/ssl/ssl.h
|
||||
@@ -121,14 +121,17 @@ SSL_IMPORT PRFileDesc *DTLS_ImportFD(PRFileDesc *model, PRFileDesc *fd);
|
||||
#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. */
|
||||
+/* 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. The advantage of false start is that
|
||||
+ * it saves a round trip for client-speaks-first protocols when performing a
|
||||
+ * full handshake.
|
||||
+ *
|
||||
+ * In addition to enabling this option, the application must register a
|
||||
+ * callback using the SSL_SetCanFalseStartCallback function.
|
||||
+ */
|
||||
|
||||
/* For SSL 3.0 and TLS 1.0, by default we prevent chosen plaintext attacks
|
||||
* on SSL CBC mode cipher suites (see RFC 4346 Section F.3) by splitting
|
||||
@@ -653,14 +656,45 @@ SSL_IMPORT SECStatus SSL_SetMaxServerCacheLocks(PRUint32 maxLocks);
|
||||
SSL_IMPORT SECStatus SSL_InheritMPServerSIDCache(const char * envString);
|
||||
|
||||
/*
|
||||
-** Set the callback on a particular socket that gets called when we finish
|
||||
-** performing a handshake.
|
||||
+** Set the callback that gets called when a TLS handshake is complete. The
|
||||
+** handshake callback is called after verifying the peer's Finished message and
|
||||
+** before processing incoming application data.
|
||||
+**
|
||||
+** For the initial handshake: If the handshake false started (see
|
||||
+** SSL_ENABLE_FALSE_START), then application data may already have been sent
|
||||
+** before the handshake callback is called. If we did not false start then the
|
||||
+** callback will get called before any application data is sent.
|
||||
*/
|
||||
typedef void (PR_CALLBACK *SSLHandshakeCallback)(PRFileDesc *fd,
|
||||
void *client_data);
|
||||
SSL_IMPORT SECStatus SSL_HandshakeCallback(PRFileDesc *fd,
|
||||
SSLHandshakeCallback cb, void *client_data);
|
||||
|
||||
+/* Applications that wish to enable TLS false start must set this callback
|
||||
+** function. NSS will invoke the functon to determine if a particular
|
||||
+** connection should use false start or not. SECSuccess indicates that the
|
||||
+** callback completed successfully, and if so *canFalseStart indicates if false
|
||||
+** start can be used. If the callback does not return SECSuccess then the
|
||||
+** handshake will be canceled. NSS's recommended criteria can be evaluated by
|
||||
+** calling SSL_RecommendedCanFalseStart.
|
||||
+**
|
||||
+** If no false start callback is registered then false start will never be
|
||||
+** done, even if the SSL_ENABLE_FALSE_START option is enabled.
|
||||
+**/
|
||||
+typedef SECStatus (PR_CALLBACK *SSLCanFalseStartCallback)(
|
||||
+ PRFileDesc *fd, void *arg, PRBool *canFalseStart);
|
||||
+
|
||||
+SSL_IMPORT SECStatus SSL_SetCanFalseStartCallback(
|
||||
+ PRFileDesc *fd, SSLCanFalseStartCallback callback, void *arg);
|
||||
+
|
||||
+/* This function sets *canFalseStart according to the recommended criteria for
|
||||
+** false start. These criteria may change from release to release and may depend
|
||||
+** on which handshake features have been negotiated and/or properties of the
|
||||
+** certifciates/keys used on the connection.
|
||||
+*/
|
||||
+SSL_IMPORT SECStatus SSL_RecommendedCanFalseStart(PRFileDesc *fd,
|
||||
+ PRBool *canFalseStart);
|
||||
+
|
||||
/*
|
||||
** For the server, request a new handshake. For the client, begin a new
|
||||
** handshake. If flushCache is non-zero, the SSL3 cache entry will be
|
||||
diff --git a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c
|
||||
index 61d24d9..f39ba09 100644
|
||||
--- a/nss/lib/ssl/ssl3con.c
|
||||
+++ b/nss/lib/ssl/ssl3con.c
|
||||
@@ -2535,7 +2535,7 @@ ssl3_SendRecord( sslSocket * ss,
|
||||
SSL_TRC(3, ("%d: SSL3[%d] SendRecord type: %s nIn=%d",
|
||||
SSL_GETPID(), ss->fd, ssl3_DecodeContentType(type),
|
||||
nIn));
|
||||
- PRINT_BUF(3, (ss, "Send record (plain text)", pIn, nIn));
|
||||
+ PRINT_BUF(50, (ss, "Send record (plain text)", pIn, nIn));
|
||||
|
||||
PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
|
||||
|
||||
@@ -6674,36 +6674,73 @@ done:
|
||||
return rv;
|
||||
}
|
||||
|
||||
+static SECStatus
|
||||
+ssl3_CheckFalseStart(sslSocket *ss)
|
||||
+{
|
||||
+ PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
|
||||
+ PORT_Assert( !ss->ssl3.hs.authCertificatePending );
|
||||
+ PORT_Assert( !ss->ssl3.hs.canFalseStart );
|
||||
+
|
||||
+ if (!ss->canFalseStartCallback) {
|
||||
+ SSL_TRC(3, ("%d: SSL[%d]: no false start callback so no false start",
|
||||
+ SSL_GETPID(), ss->fd));
|
||||
+ } else {
|
||||
+ PRBool maybeFalseStart;
|
||||
+ SECStatus rv;
|
||||
+
|
||||
+ /* An attacker can control the selected ciphersuite so we only wish to
|
||||
+ * do False Start in the case that the selected ciphersuite is
|
||||
+ * sufficiently strong that the attack can gain no advantage.
|
||||
+ * Therefore we always require an 80-bit cipher. */
|
||||
+ ssl_GetSpecReadLock(ss);
|
||||
+ maybeFalseStart = ss->ssl3.cwSpec->cipher_def->secret_key_size >= 10;
|
||||
+ ssl_ReleaseSpecReadLock(ss);
|
||||
+
|
||||
+ if (!maybeFalseStart) {
|
||||
+ SSL_TRC(3, ("%d: SSL[%d]: no false start due to weak cipher",
|
||||
+ SSL_GETPID(), ss->fd));
|
||||
+ } else {
|
||||
+ rv = (ss->canFalseStartCallback)(ss->fd,
|
||||
+ ss->canFalseStartCallbackData,
|
||||
+ &ss->ssl3.hs.canFalseStart);
|
||||
+ if (rv == SECSuccess) {
|
||||
+ SSL_TRC(3, ("%d: SSL[%d]: false start callback returned %s",
|
||||
+ SSL_GETPID(), ss->fd,
|
||||
+ ss->ssl3.hs.canFalseStart ? "TRUE" : "FALSE"));
|
||||
+ } else {
|
||||
+ SSL_TRC(3, ("%d: SSL[%d]: false start callback failed (%s)",
|
||||
+ SSL_GETPID(), ss->fd,
|
||||
+ PR_ErrorToName(PR_GetError())));
|
||||
+ }
|
||||
+ return rv;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ ss->ssl3.hs.canFalseStart = PR_FALSE;
|
||||
+ return SECSuccess;
|
||||
+}
|
||||
+
|
||||
PRBool
|
||||
-ssl3_CanFalseStart(sslSocket *ss) {
|
||||
- PRBool rv;
|
||||
+ssl3_WaitingForStartOfServerSecondRound(sslSocket *ss)
|
||||
+{
|
||||
+ PRBool result = PR_FALSE;
|
||||
|
||||
PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
|
||||
|
||||
- /* XXX: does not take into account whether we are waiting for
|
||||
- * SSL_AuthCertificateComplete or SSL_RestartHandshakeAfterCertReq. If/when
|
||||
- * that is done, this function could return different results each time it
|
||||
- * would be called.
|
||||
- */
|
||||
+ switch (ss->ssl3.hs.ws) {
|
||||
+ case wait_new_session_ticket:
|
||||
+ result = PR_TRUE;
|
||||
+ break;
|
||||
+ case wait_change_cipher:
|
||||
+ result = !ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn);
|
||||
+ break;
|
||||
+ case wait_finished:
|
||||
+ break;
|
||||
+ default:
|
||||
+ PR_NOT_REACHED("ssl3_WaitingForStartOfServerSecondRound");
|
||||
+ }
|
||||
|
||||
- ssl_GetSpecReadLock(ss);
|
||||
- rv = ss->opt.enableFalseStart &&
|
||||
- !ss->sec.isServer &&
|
||||
- !ss->ssl3.hs.isResuming &&
|
||||
- ss->ssl3.cwSpec &&
|
||||
-
|
||||
- /* An attacker can control the selected ciphersuite so we only wish to
|
||||
- * do False Start in the case that the selected ciphersuite is
|
||||
- * sufficiently strong that the attack can gain no advantage.
|
||||
- * Therefore we require an 80-bit cipher and a forward-secret key
|
||||
- * exchange. */
|
||||
- ss->ssl3.cwSpec->cipher_def->secret_key_size >= 10 &&
|
||||
- (ss->ssl3.hs.kea_def->kea == kea_dhe_dss ||
|
||||
- ss->ssl3.hs.kea_def->kea == kea_dhe_rsa ||
|
||||
- ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa ||
|
||||
- ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa);
|
||||
- ssl_ReleaseSpecReadLock(ss);
|
||||
- return rv;
|
||||
+ return result;
|
||||
}
|
||||
|
||||
static SECStatus ssl3_SendClientSecondRound(sslSocket *ss);
|
||||
@@ -6785,6 +6822,9 @@ ssl3_SendClientSecondRound(sslSocket *ss)
|
||||
}
|
||||
if (ss->ssl3.hs.authCertificatePending &&
|
||||
(sendClientCert || ss->ssl3.sendEmptyCert || ss->firstHsDone)) {
|
||||
+ SSL_TRC(3, ("%d: SSL3[%p]: deferring ssl3_SendClientSecondRound because"
|
||||
+ " certificate authentication is still pending.",
|
||||
+ SSL_GETPID(), ss->fd));
|
||||
ss->ssl3.hs.restartTarget = ssl3_SendClientSecondRound;
|
||||
return SECWouldBlock;
|
||||
}
|
||||
@@ -6822,14 +6862,50 @@ ssl3_SendClientSecondRound(sslSocket *ss)
|
||||
goto loser; /* err code was set. */
|
||||
}
|
||||
|
||||
- /* XXX: If the server's certificate hasn't been authenticated by this
|
||||
- * point, then we may be leaking this NPN message to an attacker.
|
||||
+ /* This must be done after we've set ss->ssl3.cwSpec in
|
||||
+ * ssl3_SendChangeCipherSpecs because SSL_GetChannelInfo uses information
|
||||
+ * from cwSpec. This must be done before we call ssl3_CheckFalseStart
|
||||
+ * because the false start callback (if any) may need the information from
|
||||
+ * the functions that depend on this being set.
|
||||
*/
|
||||
+ ss->enoughFirstHsDone = PR_TRUE;
|
||||
+
|
||||
if (!ss->firstHsDone) {
|
||||
+ /* XXX: If the server's certificate hasn't been authenticated by this
|
||||
+ * point, then we may be leaking this NPN message to an attacker.
|
||||
+ */
|
||||
rv = ssl3_SendNextProto(ss);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser; /* err code was set. */
|
||||
}
|
||||
+
|
||||
+ if (ss->opt.enableFalseStart) {
|
||||
+ if (!ss->ssl3.hs.authCertificatePending) {
|
||||
+ /* When we fix bug 589047, we will need to know whether we are
|
||||
+ * false starting before we try to flush the client second
|
||||
+ * round to the network. With that in mind, we purposefully
|
||||
+ * call ssl3_CheckFalseStart before calling ssl3_SendFinished,
|
||||
+ * which includes a call to ssl3_FlushHandshake, so that
|
||||
+ * no application develops a reliance on such flushing being
|
||||
+ * done before its false start callback is called.
|
||||
+ */
|
||||
+ ssl_ReleaseXmitBufLock(ss);
|
||||
+ rv = ssl3_CheckFalseStart(ss);
|
||||
+ ssl_GetXmitBufLock(ss);
|
||||
+ if (rv != SECSuccess) {
|
||||
+ goto loser;
|
||||
+ }
|
||||
+ } else {
|
||||
+ /* The certificate authentication and the server's Finished
|
||||
+ * message are racing each other. If the certificate
|
||||
+ * authentication wins, then we will try to false start in
|
||||
+ * ssl3_AuthCertificateComplete.
|
||||
+ */
|
||||
+ SSL_TRC(3, ("%d: SSL3[%p]: deferring false start check because"
|
||||
+ " certificate authentication is still pending.",
|
||||
+ SSL_GETPID(), ss->fd));
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
rv = ssl3_SendFinished(ss, 0);
|
||||
@@ -6844,10 +6920,7 @@ ssl3_SendClientSecondRound(sslSocket *ss)
|
||||
else
|
||||
ss->ssl3.hs.ws = wait_change_cipher;
|
||||
|
||||
- /* Do the handshake callback for sslv3 here, if we can false start. */
|
||||
- if (ss->handshakeCallback != NULL && ssl3_CanFalseStart(ss)) {
|
||||
- (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
|
||||
- }
|
||||
+ PORT_Assert(ssl3_WaitingForStartOfServerSecondRound(ss));
|
||||
|
||||
return SECSuccess;
|
||||
|
||||
@@ -9421,13 +9494,6 @@ ssl3_AuthCertificate(sslSocket *ss)
|
||||
|
||||
ss->ssl3.hs.authCertificatePending = PR_TRUE;
|
||||
rv = SECSuccess;
|
||||
-
|
||||
- /* XXX: Async cert validation and False Start don't work together
|
||||
- * safely yet; if we leave False Start enabled, we may end up false
|
||||
- * starting (sending application data) before we
|
||||
- * SSL_AuthCertificateComplete has been called.
|
||||
- */
|
||||
- ss->opt.enableFalseStart = PR_FALSE;
|
||||
}
|
||||
|
||||
if (rv != SECSuccess) {
|
||||
@@ -9551,6 +9617,12 @@ ssl3_AuthCertificateComplete(sslSocket *ss, PRErrorCode error)
|
||||
} else if (ss->ssl3.hs.restartTarget != NULL) {
|
||||
sslRestartTarget target = ss->ssl3.hs.restartTarget;
|
||||
ss->ssl3.hs.restartTarget = NULL;
|
||||
+
|
||||
+ if (target == ssl3_FinishHandshake) {
|
||||
+ SSL_TRC(3,("%d: SSL3[%p]: certificate authentication lost the race"
|
||||
+ " with peer's finished message", SSL_GETPID(), ss->fd));
|
||||
+ }
|
||||
+
|
||||
rv = target(ss);
|
||||
/* Even if we blocked here, we have accomplished enough to claim
|
||||
* success. Any remaining work will be taken care of by subsequent
|
||||
@@ -9560,7 +9632,29 @@ ssl3_AuthCertificateComplete(sslSocket *ss, PRErrorCode error)
|
||||
rv = SECSuccess;
|
||||
}
|
||||
} else {
|
||||
- rv = SECSuccess;
|
||||
+ SSL_TRC(3, ("%d: SSL3[%p]: certificate authentication won the race with"
|
||||
+ " peer's finished message", SSL_GETPID(), ss->fd));
|
||||
+
|
||||
+ PORT_Assert(!ss->firstHsDone);
|
||||
+ PORT_Assert(!ss->sec.isServer);
|
||||
+ PORT_Assert(!ss->ssl3.hs.isResuming);
|
||||
+ PORT_Assert(ss->ssl3.hs.ws == wait_new_session_ticket ||
|
||||
+ ss->ssl3.hs.ws == wait_change_cipher ||
|
||||
+ ss->ssl3.hs.ws == wait_finished);
|
||||
+
|
||||
+ /* ssl3_SendClientSecondRound deferred the false start check because
|
||||
+ * certificate authentication was pending, so we do it now if we still
|
||||
+ * haven't received any of the server's second round yet.
|
||||
+ */
|
||||
+ if (ss->opt.enableFalseStart &&
|
||||
+ !ss->firstHsDone &&
|
||||
+ !ss->sec.isServer &&
|
||||
+ !ss->ssl3.hs.isResuming &&
|
||||
+ ssl3_WaitingForStartOfServerSecondRound(ss)) {
|
||||
+ rv = ssl3_CheckFalseStart(ss);
|
||||
+ } else {
|
||||
+ rv = SECSuccess;
|
||||
+ }
|
||||
}
|
||||
|
||||
done:
|
||||
@@ -10023,9 +10117,6 @@ xmit_loser:
|
||||
return rv;
|
||||
}
|
||||
|
||||
- ss->gs.writeOffset = 0;
|
||||
- ss->gs.readOffset = 0;
|
||||
-
|
||||
if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) {
|
||||
effectiveExchKeyType = kt_rsa;
|
||||
} else {
|
||||
@@ -10090,6 +10181,9 @@ xmit_loser:
|
||||
return rv;
|
||||
}
|
||||
|
||||
+/* The return type is SECStatus instead of void because this function needs
|
||||
+ * to have type sslRestartTarget.
|
||||
+ */
|
||||
SECStatus
|
||||
ssl3_FinishHandshake(sslSocket * ss)
|
||||
{
|
||||
@@ -10099,19 +10193,16 @@ ssl3_FinishHandshake(sslSocket * ss)
|
||||
|
||||
/* The first handshake is now completed. */
|
||||
ss->handshake = NULL;
|
||||
- ss->firstHsDone = PR_TRUE;
|
||||
|
||||
if (ss->ssl3.hs.cacheSID) {
|
||||
(*ss->sec.cache)(ss->sec.ci.sid);
|
||||
ss->ssl3.hs.cacheSID = PR_FALSE;
|
||||
}
|
||||
|
||||
+ ss->ssl3.hs.canFalseStart = PR_FALSE; /* False Start phase is complete */
|
||||
ss->ssl3.hs.ws = idle_handshake;
|
||||
|
||||
- /* Do the handshake callback for sslv3 here, if we cannot false start. */
|
||||
- if (ss->handshakeCallback != NULL && !ssl3_CanFalseStart(ss)) {
|
||||
- (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
|
||||
- }
|
||||
+ ssl_FinishHandshake(ss);
|
||||
|
||||
return SECSuccess;
|
||||
}
|
||||
@@ -11045,7 +11136,6 @@ process_it:
|
||||
|
||||
ssl_ReleaseSSL3HandshakeLock(ss);
|
||||
return rv;
|
||||
-
|
||||
}
|
||||
|
||||
/*
|
||||
diff --git a/nss/lib/ssl/ssl3gthr.c b/nss/lib/ssl/ssl3gthr.c
|
||||
index 6d62515..03e369d 100644
|
||||
--- a/nss/lib/ssl/ssl3gthr.c
|
||||
+++ b/nss/lib/ssl/ssl3gthr.c
|
||||
@@ -275,11 +275,17 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
|
||||
{
|
||||
SSL3Ciphertext cText;
|
||||
int rv;
|
||||
- PRBool canFalseStart = PR_FALSE;
|
||||
+ PRBool keepGoing = PR_TRUE;
|
||||
|
||||
SSL_TRC(30, ("ssl3_GatherCompleteHandshake"));
|
||||
|
||||
+ /* ssl3_HandleRecord may end up eventually calling ssl_FinishHandshake,
|
||||
+ * which requires the 1stHandshakeLock, which must be acquired before the
|
||||
+ * RecvBufLock.
|
||||
+ */
|
||||
+ PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
|
||||
PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
|
||||
+
|
||||
do {
|
||||
PRBool handleRecordNow = PR_FALSE;
|
||||
|
||||
@@ -368,20 +374,48 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
|
||||
if (rv < 0) {
|
||||
return ss->recvdCloseNotify ? 0 : rv;
|
||||
}
|
||||
+ if (rv == (int) SECSuccess && ss->gs.buf.len > 0) {
|
||||
+ /* We have application data to return to the application. This
|
||||
+ * prioritizes returning application data to the application over
|
||||
+ * completing any renegotiation handshake we may be doing.
|
||||
+ */
|
||||
+ PORT_Assert(ss->firstHsDone);
|
||||
+ PORT_Assert(cText.type == content_application_data);
|
||||
+ break;
|
||||
+ }
|
||||
|
||||
- /* If we kicked off a false start in ssl3_HandleServerHelloDone, break
|
||||
- * out of this loop early without finishing the handshake.
|
||||
- */
|
||||
- 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);
|
||||
+ PORT_Assert(keepGoing);
|
||||
+ ssl_GetSSL3HandshakeLock(ss);
|
||||
+ if (ss->ssl3.hs.ws == idle_handshake) {
|
||||
+ /* We are done with the current handshake so stop trying to
|
||||
+ * handshake. Note that it would be safe to test ss->firstHsDone
|
||||
+ * instead of ss->ssl3.hs.ws. By testing ss->ssl3.hs.ws instead,
|
||||
+ * we prioritize completing a renegotiation handshake over sending
|
||||
+ * application data.
|
||||
+ */
|
||||
+ PORT_Assert(ss->firstHsDone);
|
||||
+ PORT_Assert(!ss->ssl3.hs.canFalseStart);
|
||||
+ keepGoing = PR_FALSE;
|
||||
+ } else if (ss->ssl3.hs.canFalseStart) {
|
||||
+ /* Prioritize sending application data over trying to complete
|
||||
+ * the handshake if we're false starting.
|
||||
+ *
|
||||
+ * If we were to do this check at the beginning of the loop instead
|
||||
+ * of here, then this function would become be a no-op after
|
||||
+ * receiving the ServerHelloDone in the false start case, and we
|
||||
+ * would never complete the handshake.
|
||||
+ */
|
||||
+ PORT_Assert(!ss->firstHsDone);
|
||||
+
|
||||
+ if (ssl3_WaitingForStartOfServerSecondRound(ss)) {
|
||||
+ keepGoing = PR_FALSE;
|
||||
+ } else {
|
||||
+ ss->ssl3.hs.canFalseStart = PR_FALSE;
|
||||
+ }
|
||||
}
|
||||
- } while (ss->ssl3.hs.ws != idle_handshake &&
|
||||
- !canFalseStart &&
|
||||
- ss->gs.buf.len == 0);
|
||||
+ ssl_ReleaseSSL3HandshakeLock(ss);
|
||||
+ } while (keepGoing);
|
||||
+
|
||||
|
||||
ss->gs.readOffset = 0;
|
||||
ss->gs.writeOffset = ss->gs.buf.len;
|
||||
@@ -404,7 +438,10 @@ ssl3_GatherAppDataRecord(sslSocket *ss, int flags)
|
||||
{
|
||||
int rv;
|
||||
|
||||
+ /* ssl3_GatherCompleteHandshake requires both of these locks. */
|
||||
+ PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
|
||||
PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
|
||||
+
|
||||
do {
|
||||
rv = ssl3_GatherCompleteHandshake(ss, flags);
|
||||
} while (rv > 0 && ss->gs.buf.len == 0);
|
||||
diff --git a/nss/lib/ssl/sslauth.c b/nss/lib/ssl/sslauth.c
|
||||
index d2f57bf..cb956d4 100644
|
||||
--- a/nss/lib/ssl/sslauth.c
|
||||
+++ b/nss/lib/ssl/sslauth.c
|
||||
@@ -60,7 +60,6 @@ SSL_SecurityStatus(PRFileDesc *fd, int *op, char **cp, int *kp0, int *kp1,
|
||||
sslSocket *ss;
|
||||
const char *cipherName;
|
||||
PRBool isDes = PR_FALSE;
|
||||
- PRBool enoughFirstHsDone = PR_FALSE;
|
||||
|
||||
ss = ssl_FindSocket(fd);
|
||||
if (!ss) {
|
||||
@@ -78,14 +77,7 @@ SSL_SecurityStatus(PRFileDesc *fd, int *op, char **cp, int *kp0, int *kp1,
|
||||
*op = SSL_SECURITY_STATUS_OFF;
|
||||
}
|
||||
|
||||
- if (ss->firstHsDone) {
|
||||
- enoughFirstHsDone = PR_TRUE;
|
||||
- } else if (ss->version >= SSL_LIBRARY_VERSION_3_0 &&
|
||||
- ssl3_CanFalseStart(ss)) {
|
||||
- enoughFirstHsDone = PR_TRUE;
|
||||
- }
|
||||
-
|
||||
- if (ss->opt.useSecurity && enoughFirstHsDone) {
|
||||
+ if (ss->opt.useSecurity && ss->enoughFirstHsDone) {
|
||||
if (ss->version < SSL_LIBRARY_VERSION_3_0) {
|
||||
cipherName = ssl_cipherName[ss->sec.cipherType];
|
||||
} else {
|
||||
diff --git a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h
|
||||
index 90e9567..bf0d67f 100644
|
||||
--- a/nss/lib/ssl/sslimpl.h
|
||||
+++ b/nss/lib/ssl/sslimpl.h
|
||||
@@ -842,6 +842,8 @@ const ssl3CipherSuiteDef *suite_def;
|
||||
/* Shared state between ssl3_HandleFinished and ssl3_FinishHandshake */
|
||||
PRBool cacheSID;
|
||||
|
||||
+ PRBool canFalseStart; /* Can/did we False Start */
|
||||
+
|
||||
/* clientSigAndHash contains the contents of the signature_algorithms
|
||||
* extension (if any) from the client. This is only valid for TLS 1.2
|
||||
* or later. */
|
||||
@@ -1116,6 +1118,10 @@ struct sslSocketStr {
|
||||
unsigned long clientAuthRequested;
|
||||
unsigned long delayDisabled; /* Nagle delay disabled */
|
||||
unsigned long firstHsDone; /* first handshake is complete. */
|
||||
+ unsigned long enoughFirstHsDone; /* enough of the first handshake is
|
||||
+ * done for callbacks to be able to
|
||||
+ * retrieve channel security
|
||||
+ * parameters from the SSL socket. */
|
||||
unsigned long handshakeBegun;
|
||||
unsigned long lastWriteBlocked;
|
||||
unsigned long recvdCloseNotify; /* received SSL EOF. */
|
||||
@@ -1156,6 +1162,8 @@ const unsigned char * preferredCipher;
|
||||
void *badCertArg;
|
||||
SSLHandshakeCallback handshakeCallback;
|
||||
void *handshakeCallbackData;
|
||||
+ SSLCanFalseStartCallback canFalseStartCallback;
|
||||
+ void *canFalseStartCallbackData;
|
||||
void *pkcs11PinArg;
|
||||
SSLNextProtoCallback nextProtoCallback;
|
||||
void *nextProtoArg;
|
||||
@@ -1358,7 +1366,19 @@ extern void ssl3_SetAlwaysBlock(sslSocket *ss);
|
||||
|
||||
extern SECStatus ssl_EnableNagleDelay(sslSocket *ss, PRBool enabled);
|
||||
|
||||
-extern PRBool ssl3_CanFalseStart(sslSocket *ss);
|
||||
+extern void ssl_FinishHandshake(sslSocket *ss);
|
||||
+
|
||||
+/* Returns PR_TRUE if we are still waiting for the server to respond to our
|
||||
+ * client second round. Once we've received any part of the server's second
|
||||
+ * round then we don't bother trying to false start since it is almost always
|
||||
+ * the case that the NewSessionTicket, ChangeCipherSoec, and Finished messages
|
||||
+ * were sent in the same packet and we want to process them all at the same
|
||||
+ * time. If we were to try to false start in the middle of the server's second
|
||||
+ * round, then we would increase the number of I/O operations
|
||||
+ * (SSL_ForceHandshake/PR_Recv/PR_Send/etc.) needed to finish the handshake.
|
||||
+ */
|
||||
+extern PRBool ssl3_WaitingForStartOfServerSecondRound(sslSocket *ss);
|
||||
+
|
||||
extern SECStatus
|
||||
ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec,
|
||||
PRBool isServer,
|
||||
diff --git a/nss/lib/ssl/sslinfo.c b/nss/lib/ssl/sslinfo.c
|
||||
index 9f2597e..d0c23b7 100644
|
||||
--- a/nss/lib/ssl/sslinfo.c
|
||||
+++ b/nss/lib/ssl/sslinfo.c
|
||||
@@ -26,7 +26,6 @@ SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len)
|
||||
sslSocket * ss;
|
||||
SSLChannelInfo inf;
|
||||
sslSessionID * sid;
|
||||
- PRBool enoughFirstHsDone = PR_FALSE;
|
||||
|
||||
if (!info || len < sizeof inf.length) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
@@ -43,14 +42,7 @@ SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info, PRUintn len)
|
||||
memset(&inf, 0, sizeof inf);
|
||||
inf.length = PR_MIN(sizeof inf, len);
|
||||
|
||||
- if (ss->firstHsDone) {
|
||||
- enoughFirstHsDone = PR_TRUE;
|
||||
- } else if (ss->version >= SSL_LIBRARY_VERSION_3_0 &&
|
||||
- ssl3_CanFalseStart(ss)) {
|
||||
- enoughFirstHsDone = PR_TRUE;
|
||||
- }
|
||||
-
|
||||
- if (ss->opt.useSecurity && enoughFirstHsDone) {
|
||||
+ if (ss->opt.useSecurity && ss->enoughFirstHsDone) {
|
||||
sid = ss->sec.ci.sid;
|
||||
inf.protocolVersion = ss->version;
|
||||
inf.authKeyBits = ss->sec.authKeyBits;
|
||||
diff --git a/nss/lib/ssl/sslreveal.c b/nss/lib/ssl/sslreveal.c
|
||||
index dc14794..d972998 100644
|
||||
--- a/nss/lib/ssl/sslreveal.c
|
||||
+++ b/nss/lib/ssl/sslreveal.c
|
||||
@@ -77,7 +77,6 @@ SSL_HandshakeNegotiatedExtension(PRFileDesc * socket,
|
||||
{
|
||||
/* some decisions derived from SSL_GetChannelInfo */
|
||||
sslSocket * sslsocket = NULL;
|
||||
- PRBool enoughFirstHsDone = PR_FALSE;
|
||||
|
||||
if (!pYes) {
|
||||
PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
@@ -93,14 +92,8 @@ SSL_HandshakeNegotiatedExtension(PRFileDesc * socket,
|
||||
|
||||
*pYes = PR_FALSE;
|
||||
|
||||
- if (sslsocket->firstHsDone) {
|
||||
- enoughFirstHsDone = PR_TRUE;
|
||||
- } else if (sslsocket->ssl3.initialized && ssl3_CanFalseStart(sslsocket)) {
|
||||
- enoughFirstHsDone = PR_TRUE;
|
||||
- }
|
||||
-
|
||||
/* according to public API SSL_GetChannelInfo, this doesn't need a lock */
|
||||
- if (sslsocket->opt.useSecurity && enoughFirstHsDone) {
|
||||
+ if (sslsocket->opt.useSecurity) {
|
||||
if (sslsocket->ssl3.initialized) { /* SSL3 and TLS */
|
||||
/* now we know this socket went through ssl3_InitState() and
|
||||
* ss->xtnData got initialized, which is the only member accessed by
|
||||
diff --git a/nss/lib/ssl/sslsecur.c b/nss/lib/ssl/sslsecur.c
|
||||
index 49bb42b..d0df442 100644
|
||||
--- a/nss/lib/ssl/sslsecur.c
|
||||
+++ b/nss/lib/ssl/sslsecur.c
|
||||
@@ -97,23 +97,13 @@ ssl_Do1stHandshake(sslSocket *ss)
|
||||
ss->securityHandshake = 0;
|
||||
}
|
||||
if (ss->handshake == 0) {
|
||||
- ssl_GetRecvBufLock(ss);
|
||||
- ss->gs.recordLen = 0;
|
||||
- ssl_ReleaseRecvBufLock(ss);
|
||||
-
|
||||
- SSL_TRC(3, ("%d: SSL[%d]: handshake is completed",
|
||||
- SSL_GETPID(), ss->fd));
|
||||
- /* call handshake callback for ssl v2 */
|
||||
- /* for v3 this is done in ssl3_HandleFinished() */
|
||||
- if ((ss->handshakeCallback != NULL) && /* has callback */
|
||||
- (!ss->firstHsDone) && /* only first time */
|
||||
- (ss->version < SSL_LIBRARY_VERSION_3_0)) { /* not ssl3 */
|
||||
- ss->firstHsDone = PR_TRUE;
|
||||
- (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
|
||||
+ /* for v3 this is done in ssl3_FinishHandshake */
|
||||
+ if (!ss->firstHsDone && ss->version < SSL_LIBRARY_VERSION_3_0) {
|
||||
+ ssl_GetRecvBufLock(ss);
|
||||
+ ss->gs.recordLen = 0;
|
||||
+ ssl_FinishHandshake(ss);
|
||||
+ ssl_ReleaseRecvBufLock(ss);
|
||||
}
|
||||
- ss->firstHsDone = PR_TRUE;
|
||||
- ss->gs.writeOffset = 0;
|
||||
- ss->gs.readOffset = 0;
|
||||
break;
|
||||
}
|
||||
rv = (*ss->handshake)(ss);
|
||||
@@ -134,6 +124,24 @@ ssl_Do1stHandshake(sslSocket *ss)
|
||||
return rv;
|
||||
}
|
||||
|
||||
+void
|
||||
+ssl_FinishHandshake(sslSocket *ss)
|
||||
+{
|
||||
+ PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
|
||||
+ PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
|
||||
+
|
||||
+ SSL_TRC(3, ("%d: SSL[%d]: handshake is completed", SSL_GETPID(), ss->fd));
|
||||
+
|
||||
+ ss->firstHsDone = PR_TRUE;
|
||||
+ ss->enoughFirstHsDone = PR_TRUE;
|
||||
+ ss->gs.writeOffset = 0;
|
||||
+ ss->gs.readOffset = 0;
|
||||
+
|
||||
+ if (ss->handshakeCallback) {
|
||||
+ (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Handshake function that blocks. Used to force a
|
||||
* retry on a connection on the next read/write.
|
||||
@@ -206,6 +214,7 @@ SSL_ResetHandshake(PRFileDesc *s, PRBool asServer)
|
||||
ssl_Get1stHandshakeLock(ss);
|
||||
|
||||
ss->firstHsDone = PR_FALSE;
|
||||
+ ss->enoughFirstHsDone = PR_FALSE;
|
||||
if ( asServer ) {
|
||||
ss->handshake = ssl2_BeginServerHandshake;
|
||||
ss->handshaking = sslHandshakingAsServer;
|
||||
@@ -221,6 +230,8 @@ SSL_ResetHandshake(PRFileDesc *s, PRBool asServer)
|
||||
ssl_ReleaseRecvBufLock(ss);
|
||||
|
||||
ssl_GetSSL3HandshakeLock(ss);
|
||||
+ ss->ssl3.hs.canFalseStart = PR_FALSE;
|
||||
+ ss->ssl3.hs.restartTarget = NULL;
|
||||
|
||||
/*
|
||||
** Blow away old security state and get a fresh setup.
|
||||
@@ -331,6 +342,71 @@ SSL_HandshakeCallback(PRFileDesc *fd, SSLHandshakeCallback cb,
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
+/* Register an application callback to be called when false start may happen.
|
||||
+** Acquires and releases HandshakeLock.
|
||||
+*/
|
||||
+SECStatus
|
||||
+SSL_SetCanFalseStartCallback(PRFileDesc *fd, SSLCanFalseStartCallback cb,
|
||||
+ void *arg)
|
||||
+{
|
||||
+ sslSocket *ss;
|
||||
+
|
||||
+ ss = ssl_FindSocket(fd);
|
||||
+ if (!ss) {
|
||||
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetCanFalseStartCallback",
|
||||
+ SSL_GETPID(), fd));
|
||||
+ return SECFailure;
|
||||
+ }
|
||||
+
|
||||
+ if (!ss->opt.useSecurity) {
|
||||
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
+ return SECFailure;
|
||||
+ }
|
||||
+
|
||||
+ ssl_Get1stHandshakeLock(ss);
|
||||
+ ssl_GetSSL3HandshakeLock(ss);
|
||||
+
|
||||
+ ss->canFalseStartCallback = cb;
|
||||
+ ss->canFalseStartCallbackData = arg;
|
||||
+
|
||||
+ ssl_ReleaseSSL3HandshakeLock(ss);
|
||||
+ ssl_Release1stHandshakeLock(ss);
|
||||
+
|
||||
+ return SECSuccess;
|
||||
+}
|
||||
+
|
||||
+SECStatus
|
||||
+SSL_RecommendedCanFalseStart(PRFileDesc *fd, PRBool *canFalseStart)
|
||||
+{
|
||||
+ sslSocket *ss;
|
||||
+
|
||||
+ *canFalseStart = PR_FALSE;
|
||||
+ ss = ssl_FindSocket(fd);
|
||||
+ if (!ss) {
|
||||
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_RecommendedCanFalseStart",
|
||||
+ SSL_GETPID(), fd));
|
||||
+ return SECFailure;
|
||||
+ }
|
||||
+
|
||||
+ if (!ss->ssl3.initialized) {
|
||||
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
||||
+ return SECFailure;
|
||||
+ }
|
||||
+
|
||||
+ if (ss->version < SSL_LIBRARY_VERSION_3_0) {
|
||||
+ PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
|
||||
+ return SECFailure;
|
||||
+ }
|
||||
+
|
||||
+ /* Require a forward-secret key exchange. */
|
||||
+ *canFalseStart = ss->ssl3.hs.kea_def->kea == kea_dhe_dss ||
|
||||
+ ss->ssl3.hs.kea_def->kea == kea_dhe_rsa ||
|
||||
+ ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa ||
|
||||
+ ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa;
|
||||
+
|
||||
+ return SECSuccess;
|
||||
+}
|
||||
+
|
||||
/* Try to make progress on an SSL handshake by attempting to read the
|
||||
** next handshake from the peer, and sending any responses.
|
||||
** For non-blocking sockets, returns PR_ERROR_WOULD_BLOCK if it cannot
|
||||
@@ -524,6 +600,9 @@ DoRecv(sslSocket *ss, unsigned char *out, int len, int flags)
|
||||
int amount;
|
||||
int available;
|
||||
|
||||
+ /* ssl3_GatherAppDataRecord may call ssl_FinishHandshake, which needs the
|
||||
+ * 1stHandshakeLock. */
|
||||
+ ssl_Get1stHandshakeLock(ss);
|
||||
ssl_GetRecvBufLock(ss);
|
||||
|
||||
available = ss->gs.writeOffset - ss->gs.readOffset;
|
||||
@@ -590,6 +669,7 @@ DoRecv(sslSocket *ss, unsigned char *out, int len, int flags)
|
||||
|
||||
done:
|
||||
ssl_ReleaseRecvBufLock(ss);
|
||||
+ ssl_Release1stHandshakeLock(ss);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -1156,7 +1236,7 @@ ssl_SecureRead(sslSocket *ss, unsigned char *buf, int len)
|
||||
int
|
||||
ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
|
||||
{
|
||||
- int rv = 0;
|
||||
+ int rv = 0;
|
||||
|
||||
SSL_TRC(2, ("%d: SSL[%d]: SecureSend: sending %d bytes",
|
||||
SSL_GETPID(), ss->fd, len));
|
||||
@@ -1191,19 +1271,15 @@ ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
|
||||
ss->writerThread = PR_GetCurrentThread();
|
||||
/* If any of these is non-zero, the initial handshake is not done. */
|
||||
if (!ss->firstHsDone) {
|
||||
- PRBool canFalseStart = PR_FALSE;
|
||||
+ PRBool falseStart = PR_FALSE;
|
||||
ssl_Get1stHandshakeLock(ss);
|
||||
- if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
|
||||
+ if (ss->opt.enableFalseStart &&
|
||||
+ ss->version >= SSL_LIBRARY_VERSION_3_0) {
|
||||
ssl_GetSSL3HandshakeLock(ss);
|
||||
- if ((ss->ssl3.hs.ws == wait_change_cipher ||
|
||||
- ss->ssl3.hs.ws == wait_finished ||
|
||||
- ss->ssl3.hs.ws == wait_new_session_ticket) &&
|
||||
- ssl3_CanFalseStart(ss)) {
|
||||
- canFalseStart = PR_TRUE;
|
||||
- }
|
||||
+ falseStart = ss->ssl3.hs.canFalseStart;
|
||||
ssl_ReleaseSSL3HandshakeLock(ss);
|
||||
}
|
||||
- if (!canFalseStart &&
|
||||
+ if (!falseStart &&
|
||||
(ss->handshake || ss->nextHandshake || ss->securityHandshake)) {
|
||||
rv = ssl_Do1stHandshake(ss);
|
||||
}
|
||||
@@ -1228,6 +1304,17 @@ ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
|
||||
goto done;
|
||||
}
|
||||
|
||||
+ if (!ss->firstHsDone) {
|
||||
+ PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_3_0);
|
||||
+#ifdef DEBUG
|
||||
+ ssl_GetSSL3HandshakeLock(ss);
|
||||
+ PORT_Assert(ss->ssl3.hs.canFalseStart);
|
||||
+ ssl_ReleaseSSL3HandshakeLock(ss);
|
||||
+#endif
|
||||
+ SSL_TRC(3, ("%d: SSL[%d]: SecureSend: sending data due to false start",
|
||||
+ SSL_GETPID(), ss->fd));
|
||||
+ }
|
||||
+
|
||||
/* Send out the data using one of these functions:
|
||||
* ssl2_SendClear, ssl2_SendStream, ssl2_SendBlock,
|
||||
* ssl3_SendApplicationData
|
||||
diff --git a/nss/lib/ssl/sslsock.c b/nss/lib/ssl/sslsock.c
|
||||
index cd4a7a7..73e069b 100644
|
||||
--- a/nss/lib/ssl/sslsock.c
|
||||
+++ b/nss/lib/ssl/sslsock.c
|
||||
@@ -349,6 +349,8 @@ ssl_DupSocket(sslSocket *os)
|
||||
ss->badCertArg = os->badCertArg;
|
||||
ss->handshakeCallback = os->handshakeCallback;
|
||||
ss->handshakeCallbackData = os->handshakeCallbackData;
|
||||
+ ss->canFalseStartCallback = os->canFalseStartCallback;
|
||||
+ ss->canFalseStartCallbackData = os->canFalseStartCallbackData;
|
||||
ss->pkcs11PinArg = os->pkcs11PinArg;
|
||||
|
||||
/* Create security data */
|
||||
@@ -2341,10 +2343,14 @@ ssl_Poll(PRFileDesc *fd, PRInt16 how_flags, PRInt16 *p_out_flags)
|
||||
} else if (new_flags & PR_POLL_WRITE) {
|
||||
/* The caller is trying to write, but the handshake is
|
||||
** blocked waiting for data to read, and the first
|
||||
- ** handshake has been sent. so do NOT to poll on write.
|
||||
+ ** handshake has been sent. So do NOT to poll on write
|
||||
+ ** unless we did false start.
|
||||
*/
|
||||
- new_flags ^= PR_POLL_WRITE; /* don't select on write. */
|
||||
- new_flags |= PR_POLL_READ; /* do select on read. */
|
||||
+ if (!(ss->version >= SSL_LIBRARY_VERSION_3_0 &&
|
||||
+ ss->ssl3.hs.canFalseStart)) {
|
||||
+ new_flags ^= PR_POLL_WRITE; /* don't select on write. */
|
||||
+ }
|
||||
+ new_flags |= PR_POLL_READ; /* do select on read. */
|
||||
}
|
||||
}
|
||||
} else if ((new_flags & PR_POLL_READ) && (SSL_DataPending(fd) > 0)) {
|
||||
--
|
||||
1.7.9.5
|
||||
|
|
@ -19,6 +19,7 @@ SRC_URI = "\
|
|||
file://nss-3.15.1-fix-CVE-2013-1741.patch \
|
||||
file://nss-3.15.1-fix-CVE-2013-5605.patch \
|
||||
file://nss-CVE-2014-1492.patch \
|
||||
file://nss-CVE-2013-1740.patch \
|
||||
"
|
||||
SRC_URI_append_class-target = "\
|
||||
file://nss.pc.in \
|
||||
|
|
Loading…
Reference in New Issue