| Index: net/third_party/nss/patches/canfalsestart.patch
|
| ===================================================================
|
| --- net/third_party/nss/patches/canfalsestart.patch (revision 242942)
|
| +++ net/third_party/nss/patches/canfalsestart.patch (working copy)
|
| @@ -1,837 +0,0 @@
|
| -Index: net/third_party/nss/ssl/ssl.h
|
| -===================================================================
|
| ---- net/third_party/nss/ssl/ssl.h (revision 227672)
|
| -+++ net/third_party/nss/ssl/ssl.h (working copy)
|
| -@@ -121,14 +121,17 @@
|
| - #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
|
| -@@ -741,14 +744,45 @@
|
| - 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
|
| -Index: net/third_party/nss/ssl/ssl3con.c
|
| -===================================================================
|
| ---- net/third_party/nss/ssl/ssl3con.c (revision 227672)
|
| -+++ net/third_party/nss/ssl/ssl3con.c (working copy)
|
| -@@ -2890,7 +2890,7 @@
|
| - 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) );
|
| -
|
| -@@ -7344,36 +7344,72 @@
|
| - 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;
|
| -
|
| - 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;
|
| -+ default:
|
| -+ result = PR_FALSE;
|
| -+ break;
|
| -+ }
|
| -
|
| -- 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);
|
| -@@ -7463,6 +7499,9 @@
|
| - }
|
| - 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;
|
| - }
|
| -@@ -7500,20 +7539,59 @@
|
| - 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. */
|
| - }
|
| - }
|
| -+
|
| - rv = ssl3_SendEncryptedExtensions(ss);
|
| - if (rv != SECSuccess) {
|
| - goto loser; /* err code was set. */
|
| - }
|
| -
|
| -+ if (!ss->firstHsDone) {
|
| -+ 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);
|
| - if (rv != SECSuccess) {
|
| - goto loser; /* err code was set. */
|
| -@@ -7526,10 +7604,7 @@
|
| - 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;
|
| -
|
| -@@ -10147,13 +10222,6 @@
|
| -
|
| - 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) {
|
| -@@ -10278,6 +10346,12 @@
|
| - } 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
|
| -@@ -10287,7 +10361,27 @@
|
| - 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 != idle_handshake);
|
| -+
|
| -+ if (ss->opt.enableFalseStart &&
|
| -+ !ss->firstHsDone &&
|
| -+ !ss->sec.isServer &&
|
| -+ !ss->ssl3.hs.isResuming &&
|
| -+ ssl3_WaitingForStartOfServerSecondRound(ss)) {
|
| -+ /* 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.
|
| -+ */
|
| -+ rv = ssl3_CheckFalseStart(ss);
|
| -+ } else {
|
| -+ rv = SECSuccess;
|
| -+ }
|
| - }
|
| -
|
| - done:
|
| -@@ -10913,9 +11007,6 @@
|
| - return rv;
|
| - }
|
| -
|
| -- ss->gs.writeOffset = 0;
|
| -- ss->gs.readOffset = 0;
|
| --
|
| - if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) {
|
| - effectiveExchKeyType = kt_rsa;
|
| - } else {
|
| -@@ -10980,6 +11071,9 @@
|
| - return rv;
|
| - }
|
| -
|
| -+/* The return type is SECStatus instead of void because this function needs
|
| -+ * to have type sslRestartTarget.
|
| -+ */
|
| - SECStatus
|
| - ssl3_FinishHandshake(sslSocket * ss)
|
| - {
|
| -@@ -10989,19 +11083,16 @@
|
| -
|
| - /* 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;
|
| - }
|
| -@@ -11966,7 +12057,6 @@
|
| -
|
| - ssl_ReleaseSSL3HandshakeLock(ss);
|
| - return rv;
|
| --
|
| - }
|
| -
|
| - /*
|
| -Index: net/third_party/nss/ssl/ssl3gthr.c
|
| -===================================================================
|
| ---- net/third_party/nss/ssl/ssl3gthr.c (revision 227672)
|
| -+++ net/third_party/nss/ssl/ssl3gthr.c (working copy)
|
| -@@ -275,11 +275,17 @@
|
| - {
|
| - 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;
|
| -
|
| -@@ -364,24 +370,52 @@
|
| -
|
| - cText.buf = &ss->gs.inbuf;
|
| - rv = ssl3_HandleRecord(ss, &cText, &ss->gs.buf);
|
| -+
|
| -+ 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 (rv < 0) {
|
| - return ss->recvdCloseNotify ? 0 : rv;
|
| - }
|
| -
|
| -- /* 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 @@
|
| - {
|
| - 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);
|
| -Index: net/third_party/nss/ssl/sslauth.c
|
| -===================================================================
|
| ---- net/third_party/nss/ssl/sslauth.c (revision 227672)
|
| -+++ net/third_party/nss/ssl/sslauth.c (working copy)
|
| -@@ -100,7 +100,6 @@
|
| - sslSocket *ss;
|
| - const char *cipherName;
|
| - PRBool isDes = PR_FALSE;
|
| -- PRBool enoughFirstHsDone = PR_FALSE;
|
| -
|
| - ss = ssl_FindSocket(fd);
|
| - if (!ss) {
|
| -@@ -118,14 +117,7 @@
|
| - *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 {
|
| -Index: net/third_party/nss/ssl/sslimpl.h
|
| -===================================================================
|
| ---- net/third_party/nss/ssl/sslimpl.h (revision 227672)
|
| -+++ net/third_party/nss/ssl/sslimpl.h (working copy)
|
| -@@ -881,6 +881,8 @@
|
| - /* 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. */
|
| -@@ -1162,6 +1164,10 @@
|
| - 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. */
|
| -@@ -1210,6 +1216,8 @@
|
| - void *badCertArg;
|
| - SSLHandshakeCallback handshakeCallback;
|
| - void *handshakeCallbackData;
|
| -+ SSLCanFalseStartCallback canFalseStartCallback;
|
| -+ void *canFalseStartCallbackData;
|
| - void *pkcs11PinArg;
|
| - SSLNextProtoCallback nextProtoCallback;
|
| - void *nextProtoArg;
|
| -@@ -1423,7 +1431,19 @@
|
| -
|
| - 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,
|
| -Index: net/third_party/nss/ssl/sslinfo.c
|
| -===================================================================
|
| ---- net/third_party/nss/ssl/sslinfo.c (revision 227672)
|
| -+++ net/third_party/nss/ssl/sslinfo.c (working copy)
|
| -@@ -26,7 +26,6 @@
|
| - 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 @@
|
| - 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;
|
| -Index: net/third_party/nss/ssl/sslsecur.c
|
| -===================================================================
|
| ---- net/third_party/nss/ssl/sslsecur.c (revision 227672)
|
| -+++ net/third_party/nss/ssl/sslsecur.c (working copy)
|
| -@@ -97,23 +97,13 @@
|
| - 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 @@
|
| - 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_Get1stHandshakeLock(ss);
|
| -
|
| - ss->firstHsDone = PR_FALSE;
|
| -+ ss->enoughFirstHsDone = PR_FALSE;
|
| - if ( asServer ) {
|
| - ss->handshake = ssl2_BeginServerHandshake;
|
| - ss->handshaking = sslHandshakingAsServer;
|
| -@@ -221,6 +230,8 @@
|
| - 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 @@
|
| - 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 @@
|
| - 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 @@
|
| -
|
| - done:
|
| - ssl_ReleaseRecvBufLock(ss);
|
| -+ ssl_Release1stHandshakeLock(ss);
|
| - return rv;
|
| - }
|
| -
|
| -@@ -1156,7 +1236,8 @@
|
| - int
|
| - ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
|
| - {
|
| -- int rv = 0;
|
| -+ int rv = 0;
|
| -+ PRBool falseStart = PR_FALSE;
|
| -
|
| - SSL_TRC(2, ("%d: SSL[%d]: SecureSend: sending %d bytes",
|
| - SSL_GETPID(), ss->fd, len));
|
| -@@ -1191,19 +1272,14 @@
|
| - ss->writerThread = PR_GetCurrentThread();
|
| - /* If any of these is non-zero, the initial handshake is not done. */
|
| - if (!ss->firstHsDone) {
|
| -- PRBool canFalseStart = 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 @@
|
| - 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
|
| -Index: net/third_party/nss/ssl/sslsock.c
|
| -===================================================================
|
| ---- net/third_party/nss/ssl/sslsock.c (revision 227672)
|
| -+++ net/third_party/nss/ssl/sslsock.c (working copy)
|
| -@@ -366,6 +366,8 @@
|
| - ss->badCertArg = os->badCertArg;
|
| - ss->handshakeCallback = os->handshakeCallback;
|
| - ss->handshakeCallbackData = os->handshakeCallbackData;
|
| -+ ss->canFalseStartCallback = os->canFalseStartCallback;
|
| -+ ss->canFalseStartCallbackData = os->canFalseStartCallbackData;
|
| - ss->pkcs11PinArg = os->pkcs11PinArg;
|
| - ss->getChannelID = os->getChannelID;
|
| - ss->getChannelIDArg = os->getChannelIDArg;
|
| -@@ -2457,10 +2459,14 @@
|
| - } 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)) {
|
|
|