| Index: net/third_party/nss/patches/canfalsestart.patch
|
| ===================================================================
|
| --- net/third_party/nss/patches/canfalsestart.patch (revision 0)
|
| +++ net/third_party/nss/patches/canfalsestart.patch (revision 0)
|
| @@ -0,0 +1,637 @@
|
| +Index: net/third_party/nss/ssl/ssl.h
|
| +===================================================================
|
| +--- net/third_party/nss/ssl/ssl.h (revision 227363)
|
| ++++ net/third_party/nss/ssl/ssl.h (working copy)
|
| +@@ -121,14 +121,22 @@
|
| + #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.
|
| ++ *
|
| ++ * See SSL_DefaultCanFalseStart for the default criteria that NSS uses to
|
| ++ * determine whether to false start or not. See SSL_SetCanFalseStartCallback
|
| ++ * for how to change that criteria. In addition to those criteria, false start
|
| ++ * will only be done when the server selects a cipher suite with an effective
|
| ++ * key length of 80 bits or more (including RC4-128). Also, see
|
| ++ * SSL_HandshakeCallback for a description on how false start affects when the
|
| ++ * handshake callback gets called.
|
| ++ */
|
| +
|
| + /* 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 +749,59 @@
|
| + 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 normally gets called when the TLS handshake
|
| ++** is complete. If false start is not enabled, then the handshake callback is
|
| ++** called after verifying the peer's Finished message and before sending
|
| ++** outgoing application data and before processing incoming application data.
|
| ++**
|
| ++** If false start is enabled and there is a custom CanFalseStartCallback
|
| ++** callback set, then the handshake callback gets called after the peer's
|
| ++** Finished message has been verified, which may be after application data is
|
| ++** sent.
|
| ++**
|
| ++** If false start is enabled and there is not a custom CanFalseStartCallback
|
| ++** callback established with SSL_SetCanFalseStartCallback then the handshake
|
| ++** callback gets called before any application data is sent, which may be
|
| ++** before the peer's Finished message has been verified.
|
| + */
|
| + 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 customize TLS false start should 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.
|
| ++**
|
| ++** Applications that do not set the callback will use an internal set of
|
| ++** criteria to determine if the connection should false start. If
|
| ++** the callback is set false start will never be used without invoking the
|
| ++** callback function, but some connections (e.g. resumed connections) will
|
| ++** never use false start and therefore will not invoke the callback.
|
| ++**
|
| ++** NSS's internal criteria for this connection can be evaluated by calling
|
| ++** SSL_DefaultCanFalseStart() from the custom callback.
|
| ++**
|
| ++** See the description of SSL_HandshakeCallback for important information on
|
| ++** how registering a custom false start callback affects when the handshake
|
| ++** callback gets called.
|
| ++**/
|
| ++typedef SECStatus (PR_CALLBACK *SSLCanFalseStartCallback)(
|
| ++ PRFileDesc *fd, void *arg, PRBool *canFalseStart);
|
| ++
|
| ++SSL_IMPORT SECStatus SSL_SetCanFalseStartCallback(
|
| ++ PRFileDesc *fd, SSLCanFalseStartCallback callback, void *arg);
|
| ++
|
| ++/* A utility function that can be called from a custom CanFalseStartCallback
|
| ++** function to determine what NSS would have done for this connection if the
|
| ++** custom callback was not implemented.
|
| ++**/
|
| ++SSL_IMPORT SECStatus SSL_DefaultCanFalseStart(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/ssl3gthr.c
|
| +===================================================================
|
| +--- net/third_party/nss/ssl/ssl3gthr.c (revision 227363)
|
| ++++ net/third_party/nss/ssl/ssl3gthr.c (working copy)
|
| +@@ -374,9 +374,7 @@
|
| + */
|
| + 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);
|
| ++ canFalseStart = ss->ssl3.hs.canFalseStart;
|
| + ssl_ReleaseSSL3HandshakeLock(ss);
|
| + }
|
| + } while (ss->ssl3.hs.ws != idle_handshake &&
|
| +Index: net/third_party/nss/ssl/sslinfo.c
|
| +===================================================================
|
| +--- net/third_party/nss/ssl/sslinfo.c (revision 227363)
|
| ++++ 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/sslauth.c
|
| +===================================================================
|
| +--- net/third_party/nss/ssl/sslauth.c (revision 227363)
|
| ++++ 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 227363)
|
| ++++ 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,6 @@
|
| +
|
| + extern SECStatus ssl_EnableNagleDelay(sslSocket *ss, PRBool enabled);
|
| +
|
| +-extern PRBool ssl3_CanFalseStart(sslSocket *ss);
|
| + extern SECStatus
|
| + ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec,
|
| + PRBool isServer,
|
| +Index: net/third_party/nss/ssl/sslsecur.c
|
| +===================================================================
|
| +--- net/third_party/nss/ssl/sslsecur.c (revision 227363)
|
| ++++ net/third_party/nss/ssl/sslsecur.c (working copy)
|
| +@@ -99,21 +99,12 @@
|
| + if (ss->handshake == 0) {
|
| + ssl_GetRecvBufLock(ss);
|
| + ss->gs.recordLen = 0;
|
| ++ ss->gs.writeOffset = 0;
|
| ++ ss->gs.readOffset = 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);
|
| +- }
|
| +- ss->firstHsDone = PR_TRUE;
|
| +- ss->gs.writeOffset = 0;
|
| +- ss->gs.readOffset = 0;
|
| + break;
|
| + }
|
| + rv = (*ss->handshake)(ss);
|
| +@@ -206,6 +197,7 @@
|
| + ssl_Get1stHandshakeLock(ss);
|
| +
|
| + ss->firstHsDone = PR_FALSE;
|
| ++ ss->enoughFirstHsDone = PR_FALSE;
|
| + if ( asServer ) {
|
| + ss->handshake = ssl2_BeginServerHandshake;
|
| + ss->handshaking = sslHandshakingAsServer;
|
| +@@ -221,6 +213,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.
|
| +@@ -266,7 +260,7 @@
|
| +
|
| + /* SSL v2 protocol does not support subsequent handshakes. */
|
| + if (ss->version < SSL_LIBRARY_VERSION_3_0) {
|
| +- PORT_SetError(SEC_ERROR_INVALID_ARGS);
|
| ++ PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
|
| + rv = SECFailure;
|
| + } else {
|
| + ssl_GetSSL3HandshakeLock(ss);
|
| +@@ -331,6 +325,75 @@
|
| + 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 *client_data)
|
| ++{
|
| ++ 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 = client_data;
|
| ++
|
| ++ ssl_ReleaseSSL3HandshakeLock(ss);
|
| ++ ssl_Release1stHandshakeLock(ss);
|
| ++
|
| ++ return SECSuccess;
|
| ++}
|
| ++
|
| ++/* A utility function that can be called from a custom SSLCanFalseStartCallback
|
| ++** function to determine what NSS would have done for this connection if the
|
| ++** custom callback was not implemented.
|
| ++*/
|
| ++SECStatus
|
| ++SSL_DefaultCanFalseStart(PRFileDesc *fd, PRBool *canFalseStart)
|
| ++{
|
| ++ sslSocket *ss;
|
| ++
|
| ++ *canFalseStart = PR_FALSE;
|
| ++ ss = ssl_FindSocket(fd);
|
| ++ if (!ss) {
|
| ++ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_DefaultCanFalseStart",
|
| ++ 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
|
| +@@ -1195,12 +1258,7 @@
|
| + ssl_Get1stHandshakeLock(ss);
|
| + if (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;
|
| +- }
|
| ++ canFalseStart = ss->ssl3.hs.canFalseStart;
|
| + ssl_ReleaseSSL3HandshakeLock(ss);
|
| + }
|
| + if (!canFalseStart &&
|
| +Index: net/third_party/nss/ssl/sslsock.c
|
| +===================================================================
|
| +--- net/third_party/nss/ssl/sslsock.c (revision 227363)
|
| ++++ net/third_party/nss/ssl/sslsock.c (working copy)
|
| +@@ -2457,10 +2457,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)) {
|
| +Index: net/third_party/nss/ssl/ssl3con.c
|
| +===================================================================
|
| +--- net/third_party/nss/ssl/ssl3con.c (revision 227363)
|
| ++++ 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,35 +7344,42 @@
|
| + return rv;
|
| + }
|
| +
|
| +-PRBool
|
| +-ssl3_CanFalseStart(sslSocket *ss) {
|
| +- PRBool rv;
|
| ++static SECStatus
|
| ++ssl3_CheckFalseStart(sslSocket *ss)
|
| ++{
|
| ++ SECStatus rv;
|
| ++ PRBool maybeFalseStart = PR_TRUE;
|
| +
|
| + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
|
| ++ PORT_Assert( !ss->ssl3.hs.authCertificatePending );
|
| +
|
| +- /* 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.
|
| +- */
|
| ++ /* 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);
|
| +- rv = ss->opt.enableFalseStart &&
|
| +- !ss->sec.isServer &&
|
| +- !ss->ssl3.hs.isResuming &&
|
| +- ss->ssl3.cwSpec &&
|
| ++ if (ss->ssl3.cwSpec->cipher_def->secret_key_size < 10) {
|
| ++ ss->ssl3.hs.canFalseStart = PR_FALSE;
|
| ++ maybeFalseStart = PR_FALSE;
|
| ++ }
|
| ++ ssl_ReleaseSpecReadLock(ss);
|
| ++ if (!maybeFalseStart) {
|
| ++ return SECSuccess;
|
| ++ }
|
| +
|
| +- /* 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);
|
| ++ if (!ss->canFalseStartCallback) {
|
| ++ rv = SSL_DefaultCanFalseStart(ss->fd, &ss->ssl3.hs.canFalseStart);
|
| ++ } else {
|
| ++ rv = (ss->canFalseStartCallback)(ss->fd,
|
| ++ ss->canFalseStartCallbackData,
|
| ++ &ss->ssl3.hs.canFalseStart);
|
| ++ }
|
| ++
|
| ++ if (rv != SECSuccess) {
|
| ++ ss->ssl3.hs.canFalseStart = PR_FALSE;
|
| ++ }
|
| ++
|
| + return rv;
|
| + }
|
| +
|
| +@@ -7500,20 +7507,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,8 +7572,16 @@
|
| + 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)) {
|
| ++ if (ss->handshakeCallback &&
|
| ++ (ss->ssl3.hs.canFalseStart && !ss->canFalseStartCallback)) {
|
| ++ /* Call the handshake callback here for backwards compatibility with
|
| ++ * applications that were using false start before
|
| ++ * canFalseStartCallback was added. Note that we do this after calling
|
| ++ * ssl3_SendFinished, which includes a call to ssl3_FlushHandshake,
|
| ++ * just in case the application is relying on having the handshake
|
| ++ * messages flushed to the network before its handshake callback is
|
| ++ * called.
|
| ++ */
|
| + (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
|
| + }
|
| +
|
| +@@ -10147,13 +10201,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 +10325,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 +10340,39 @@
|
| + 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_change_cipher ||
|
| ++ ss->ssl3.hs.ws == wait_finished ||
|
| ++ ss->ssl3.hs.ws == wait_new_session_ticket);
|
| ++
|
| ++ /* ssl3_SendClientSecondRound deferred the false start check because
|
| ++ * certificate authentication was pending, so we have to do it now.
|
| ++ */
|
| ++ if (ss->opt.enableFalseStart &&
|
| ++ !ss->firstHsDone &&
|
| ++ !ss->sec.isServer &&
|
| ++ !ss->ssl3.hs.isResuming &&
|
| ++ (ss->ssl3.hs.ws == wait_change_cipher ||
|
| ++ ss->ssl3.hs.ws == wait_finished ||
|
| ++ ss->ssl3.hs.ws == wait_new_session_ticket)) {
|
| ++ rv = ssl3_CheckFalseStart(ss);
|
| ++ if (rv == SECSuccess &&
|
| ++ ss->handshakeCallback &&
|
| ++ (ss->ssl3.hs.canFalseStart && !ss->canFalseStartCallback)) {
|
| ++ /* Call the handshake callback here for backwards compatibility
|
| ++ * with applications that were using false start before
|
| ++ * canFalseStartCallback was added.
|
| ++ */
|
| ++ (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
|
| ++ }
|
| ++ } else {
|
| ++ rv = SECSuccess;
|
| ++ }
|
| + }
|
| +
|
| + done:
|
| +@@ -10983,6 +11068,8 @@
|
| + SECStatus
|
| + ssl3_FinishHandshake(sslSocket * ss)
|
| + {
|
| ++ PRBool falseStarted;
|
| ++
|
| + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
|
| + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
|
| + PORT_Assert( ss->ssl3.hs.restartTarget == NULL );
|
| +@@ -10990,6 +11077,7 @@
|
| + /* The first handshake is now completed. */
|
| + ss->handshake = NULL;
|
| + ss->firstHsDone = PR_TRUE;
|
| ++ ss->enoughFirstHsDone = PR_TRUE;
|
| +
|
| + if (ss->ssl3.hs.cacheSID) {
|
| + (*ss->sec.cache)(ss->sec.ci.sid);
|
| +@@ -10997,9 +11085,14 @@
|
| + }
|
| +
|
| + ss->ssl3.hs.ws = idle_handshake;
|
| ++ falseStarted = ss->ssl3.hs.canFalseStart;
|
| ++ ss->ssl3.hs.canFalseStart = PR_FALSE; /* False Start phase is complete */
|
| +
|
| +- /* Do the handshake callback for sslv3 here, if we cannot false start. */
|
| +- if (ss->handshakeCallback != NULL && !ssl3_CanFalseStart(ss)) {
|
| ++ /* Call the handshake callback for sslv3 here, unless we called it already
|
| ++ * for the case where false start was done without a canFalseStartCallback.
|
| ++ */
|
| ++ if (ss->handshakeCallback &&
|
| ++ !(falseStarted && !ss->canFalseStartCallback)) {
|
| + (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
|
| + }
|
| +
|
|
|