 Chromium Code Reviews
 Chromium Code Reviews Issue 27254004:
  Make SSL False Start work with asynchronous certificate validation  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src/
    
  
    Issue 27254004:
  Make SSL False Start work with asynchronous certificate validation  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src/| 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_ReleaseRecvBufLock(ss); | 
| 
wtc
2013/10/17 00:10:53
Why do we only need to set ss->gs.recordLen to 0 f
 
briansmith
2013/10/17 01:42:40
recordLen is only used for SSL 2.0:
unsigned int
 | 
| + ssl_FinishHandshake(ss); | 
| } | 
| - ss->firstHsDone = PR_TRUE; | 
| - ss->gs.writeOffset = 0; | 
| - ss->gs.readOffset = 0; | 
| break; | 
| } | 
| rv = (*ss->handshake)(ss); | 
| @@ -134,6 +124,23 @@ | 
| return rv; | 
| } | 
| +void | 
| +ssl_FinishHandshake(sslSocket *ss) | 
| 
wtc
2013/10/17 00:10:53
Should we move this function to sslcon.c, since it
 
briansmith
2013/10/17 01:42:40
This is not SSL-2.0-only. This is the functionalit
 | 
| +{ | 
| + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | 
| 
briansmith
2013/10/17 19:09:01
Wan-Teh, do you agree that this assertion is corre
 
wtc
2013/10/17 23:13:01
This seems very reasonable, but I didn't find this
 | 
| + | 
| + 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 +213,7 @@ | 
| ssl_Get1stHandshakeLock(ss); | 
| ss->firstHsDone = PR_FALSE; | 
| + ss->enoughFirstHsDone = PR_FALSE; | 
| if ( asServer ) { | 
| ss->handshake = ssl2_BeginServerHandshake; | 
| ss->handshaking = sslHandshakingAsServer; | 
| @@ -221,6 +229,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 +341,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 *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; | 
| +} | 
| + | 
| +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_DefaultCanFalseStart", | 
| 
wtc
2013/10/17 00:10:53
SSL_DefaultCanFalseStart => SSL_RecommendedCanFals
 
briansmith
2013/10/17 01:42:40
Done.
 | 
| + 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 +599,7 @@ | 
| int amount; | 
| int available; | 
| + ssl_Get1stHandshakeLock(ss); | 
| 
wtc
2013/10/17 00:10:53
Why does DoRecv() need to get the 1stHandshakeLock
 
briansmith
2013/10/17 01:42:40
It calls ssl3_GatherAppDataRecord and ssl3_GatherA
 
wtc
2013/10/17 15:28:14
I'm sorry that I still don't understand this. Coul
 | 
| ssl_GetRecvBufLock(ss); | 
| available = ss->gs.writeOffset - ss->gs.readOffset; | 
| @@ -590,6 +666,7 @@ | 
| done: | 
| ssl_ReleaseRecvBufLock(ss); | 
| + ssl_Release1stHandshakeLock(ss); | 
| return rv; | 
| } | 
| @@ -1156,7 +1233,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 +1269,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 && | 
| 
wtc
2013/10/17 00:10:53
Why do you check ss->opt.enableFalseStart?
I gues
 
briansmith
2013/10/17 01:42:40
Yes
 | 
| + 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)) { | 
| 
wtc
2013/10/17 15:28:14
Hmm... If we false started, ss->handshake etc. sho
 | 
| rv = ssl_Do1stHandshake(ss); | 
| } | 
| @@ -1228,6 +1301,21 @@ | 
| goto done; | 
| } | 
| + if (ssl_trace >= 2 && | 
| + !ss->firstHsDone && !falseStart && | 
| + ss->opt.enableFalseStart && ss->version >= SSL_LIBRARY_VERSION_3_0) { | 
| + /* We need to check ss->ssl3.hs.canFalseStart again in case we called | 
| + * ssl_Do1stHandshake, because ssl_Do1stHandshake might have changed | 
| + * it. | 
| + */ | 
| + ssl_GetSSL3HandshakeLock(ss); | 
| + falseStart = ss->ssl3.hs.canFalseStart; | 
| + ssl_ReleaseSSL3HandshakeLock(ss); | 
| 
wtc
2013/10/17 00:10:53
falseStart is set here but never used again. So li
 
briansmith
2013/10/17 01:42:40
You are right that this complicated code can be de
 | 
| + | 
| + SSL_TRC(2, ("%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 |