| OLD | NEW |
| (Empty) |
| 1 Index: net/third_party/nss/ssl/ssl.h | |
| 2 =================================================================== | |
| 3 --- net/third_party/nss/ssl/ssl.h (revision 227672) | |
| 4 +++ net/third_party/nss/ssl/ssl.h (working copy) | |
| 5 @@ -121,14 +121,17 @@ | |
| 6 #define SSL_ENABLE_FALSE_START 22 /* Enable SSL false start (off by */ | |
| 7 /* default, applies only to */ | |
| 8 /* clients). False start is a */ | |
| 9 -/* mode where an SSL client will start sending application data before */ | |
| 10 -/* verifying the server's Finished message. This means that we could end up */ | |
| 11 -/* sending data to an imposter. However, the data will be encrypted and */ | |
| 12 -/* only the true server can derive the session key. Thus, so long as the */ | |
| 13 -/* cipher isn't broken this is safe. Because of this, False Start will only */ | |
| 14 -/* occur on RSA or DH ciphersuites where the cipher's key length is >= 80 */ | |
| 15 -/* bits. The advantage of False Start is that it saves a round trip for */ | |
| 16 -/* client-speaks-first protocols when performing a full handshake. */ | |
| 17 +/* mode where an SSL client will start sending application data before | |
| 18 + * verifying the server's Finished message. This means that we could end up | |
| 19 + * sending data to an imposter. However, the data will be encrypted and | |
| 20 + * only the true server can derive the session key. Thus, so long as the | |
| 21 + * cipher isn't broken this is safe. The advantage of false start is that | |
| 22 + * it saves a round trip for client-speaks-first protocols when performing a | |
| 23 + * full handshake. | |
| 24 + * | |
| 25 + * In addition to enabling this option, the application must register a | |
| 26 + * callback using the SSL_SetCanFalseStartCallback function. | |
| 27 + */ | |
| 28 | |
| 29 /* For SSL 3.0 and TLS 1.0, by default we prevent chosen plaintext attacks | |
| 30 * on SSL CBC mode cipher suites (see RFC 4346 Section F.3) by splitting | |
| 31 @@ -741,14 +744,45 @@ | |
| 32 SSL_IMPORT SECStatus SSL_InheritMPServerSIDCache(const char * envString); | |
| 33 | |
| 34 /* | |
| 35 -** Set the callback on a particular socket that gets called when we finish | |
| 36 -** performing a handshake. | |
| 37 +** Set the callback that gets called when a TLS handshake is complete. The | |
| 38 +** handshake callback is called after verifying the peer's Finished message and | |
| 39 +** before processing incoming application data. | |
| 40 +** | |
| 41 +** For the initial handshake: If the handshake false started (see | |
| 42 +** SSL_ENABLE_FALSE_START), then application data may already have been sent | |
| 43 +** before the handshake callback is called. If we did not false start then the | |
| 44 +** callback will get called before any application data is sent. | |
| 45 */ | |
| 46 typedef void (PR_CALLBACK *SSLHandshakeCallback)(PRFileDesc *fd, | |
| 47 void *client_data); | |
| 48 SSL_IMPORT SECStatus SSL_HandshakeCallback(PRFileDesc *fd, | |
| 49 SSLHandshakeCallback cb, void *client_data); | |
| 50 | |
| 51 +/* Applications that wish to enable TLS false start must set this callback | |
| 52 +** function. NSS will invoke the functon to determine if a particular | |
| 53 +** connection should use false start or not. SECSuccess indicates that the | |
| 54 +** callback completed successfully, and if so *canFalseStart indicates if false | |
| 55 +** start can be used. If the callback does not return SECSuccess then the | |
| 56 +** handshake will be canceled. NSS's recommended criteria can be evaluated by | |
| 57 +** calling SSL_RecommendedCanFalseStart. | |
| 58 +** | |
| 59 +** If no false start callback is registered then false start will never be | |
| 60 +** done, even if the SSL_ENABLE_FALSE_START option is enabled. | |
| 61 +**/ | |
| 62 +typedef SECStatus (PR_CALLBACK *SSLCanFalseStartCallback)( | |
| 63 + PRFileDesc *fd, void *arg, PRBool *canFalseStart); | |
| 64 + | |
| 65 +SSL_IMPORT SECStatus SSL_SetCanFalseStartCallback( | |
| 66 + PRFileDesc *fd, SSLCanFalseStartCallback callback, void *arg); | |
| 67 + | |
| 68 +/* This function sets *canFalseStart according to the recommended criteria for | |
| 69 +** false start. These criteria may change from release to release and may depen
d | |
| 70 +** on which handshake features have been negotiated and/or properties of the | |
| 71 +** certifciates/keys used on the connection. | |
| 72 +*/ | |
| 73 +SSL_IMPORT SECStatus SSL_RecommendedCanFalseStart(PRFileDesc *fd, | |
| 74 + PRBool *canFalseStart); | |
| 75 + | |
| 76 /* | |
| 77 ** For the server, request a new handshake. For the client, begin a new | |
| 78 ** handshake. If flushCache is non-zero, the SSL3 cache entry will be | |
| 79 Index: net/third_party/nss/ssl/ssl3con.c | |
| 80 =================================================================== | |
| 81 --- net/third_party/nss/ssl/ssl3con.c (revision 227672) | |
| 82 +++ net/third_party/nss/ssl/ssl3con.c (working copy) | |
| 83 @@ -2890,7 +2890,7 @@ | |
| 84 SSL_TRC(3, ("%d: SSL3[%d] SendRecord type: %s nIn=%d", | |
| 85 SSL_GETPID(), ss->fd, ssl3_DecodeContentType(type), | |
| 86 nIn)); | |
| 87 - PRINT_BUF(3, (ss, "Send record (plain text)", pIn, nIn)); | |
| 88 + PRINT_BUF(50, (ss, "Send record (plain text)", pIn, nIn)); | |
| 89 | |
| 90 PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) ); | |
| 91 | |
| 92 @@ -7344,36 +7344,72 @@ | |
| 93 return rv; | |
| 94 } | |
| 95 | |
| 96 +static SECStatus | |
| 97 +ssl3_CheckFalseStart(sslSocket *ss) | |
| 98 +{ | |
| 99 + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); | |
| 100 + PORT_Assert( !ss->ssl3.hs.authCertificatePending ); | |
| 101 + PORT_Assert( !ss->ssl3.hs.canFalseStart ); | |
| 102 + | |
| 103 + if (!ss->canFalseStartCallback) { | |
| 104 + SSL_TRC(3, ("%d: SSL[%d]: no false start callback so no false start", | |
| 105 + SSL_GETPID(), ss->fd)); | |
| 106 + } else { | |
| 107 + PRBool maybeFalseStart; | |
| 108 + SECStatus rv; | |
| 109 + | |
| 110 + /* An attacker can control the selected ciphersuite so we only wish to | |
| 111 + * do False Start in the case that the selected ciphersuite is | |
| 112 + * sufficiently strong that the attack can gain no advantage. | |
| 113 + * Therefore we always require an 80-bit cipher. */ | |
| 114 + ssl_GetSpecReadLock(ss); | |
| 115 + maybeFalseStart = ss->ssl3.cwSpec->cipher_def->secret_key_size >= 10; | |
| 116 + ssl_ReleaseSpecReadLock(ss); | |
| 117 + | |
| 118 + if (!maybeFalseStart) { | |
| 119 + SSL_TRC(3, ("%d: SSL[%d]: no false start due to weak cipher", | |
| 120 + SSL_GETPID(), ss->fd)); | |
| 121 + } else { | |
| 122 + rv = (ss->canFalseStartCallback)(ss->fd, | |
| 123 + ss->canFalseStartCallbackData, | |
| 124 + &ss->ssl3.hs.canFalseStart); | |
| 125 + if (rv == SECSuccess) { | |
| 126 + SSL_TRC(3, ("%d: SSL[%d]: false start callback returned %s", | |
| 127 + SSL_GETPID(), ss->fd, | |
| 128 + ss->ssl3.hs.canFalseStart ? "TRUE" : "FALSE")); | |
| 129 + } else { | |
| 130 + SSL_TRC(3, ("%d: SSL[%d]: false start callback failed (%s)", | |
| 131 + SSL_GETPID(), ss->fd, | |
| 132 + PR_ErrorToName(PR_GetError()))); | |
| 133 + } | |
| 134 + return rv; | |
| 135 + } | |
| 136 + } | |
| 137 + | |
| 138 + ss->ssl3.hs.canFalseStart = PR_FALSE; | |
| 139 + return SECSuccess; | |
| 140 +} | |
| 141 + | |
| 142 PRBool | |
| 143 -ssl3_CanFalseStart(sslSocket *ss) { | |
| 144 - PRBool rv; | |
| 145 +ssl3_WaitingForStartOfServerSecondRound(sslSocket *ss) | |
| 146 +{ | |
| 147 + PRBool result; | |
| 148 | |
| 149 PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); | |
| 150 | |
| 151 - /* XXX: does not take into account whether we are waiting for | |
| 152 - * SSL_AuthCertificateComplete or SSL_RestartHandshakeAfterCertReq. If/when | |
| 153 - * that is done, this function could return different results each time it | |
| 154 - * would be called. | |
| 155 - */ | |
| 156 + switch (ss->ssl3.hs.ws) { | |
| 157 + case wait_new_session_ticket: | |
| 158 + result = PR_TRUE; | |
| 159 + break; | |
| 160 + case wait_change_cipher: | |
| 161 + result = !ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn); | |
| 162 + break; | |
| 163 + default: | |
| 164 + result = PR_FALSE; | |
| 165 + break; | |
| 166 + } | |
| 167 | |
| 168 - ssl_GetSpecReadLock(ss); | |
| 169 - rv = ss->opt.enableFalseStart && | |
| 170 - !ss->sec.isServer && | |
| 171 - !ss->ssl3.hs.isResuming && | |
| 172 - ss->ssl3.cwSpec && | |
| 173 - | |
| 174 - /* An attacker can control the selected ciphersuite so we only wish to | |
| 175 - * do False Start in the case that the selected ciphersuite is | |
| 176 - * sufficiently strong that the attack can gain no advantage. | |
| 177 - * Therefore we require an 80-bit cipher and a forward-secret key | |
| 178 - * exchange. */ | |
| 179 - ss->ssl3.cwSpec->cipher_def->secret_key_size >= 10 && | |
| 180 - (ss->ssl3.hs.kea_def->kea == kea_dhe_dss || | |
| 181 - ss->ssl3.hs.kea_def->kea == kea_dhe_rsa || | |
| 182 - ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa || | |
| 183 - ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa); | |
| 184 - ssl_ReleaseSpecReadLock(ss); | |
| 185 - return rv; | |
| 186 + return result; | |
| 187 } | |
| 188 | |
| 189 static SECStatus ssl3_SendClientSecondRound(sslSocket *ss); | |
| 190 @@ -7463,6 +7499,9 @@ | |
| 191 } | |
| 192 if (ss->ssl3.hs.authCertificatePending && | |
| 193 (sendClientCert || ss->ssl3.sendEmptyCert || ss->firstHsDone)) { | |
| 194 + SSL_TRC(3, ("%d: SSL3[%p]: deferring ssl3_SendClientSecondRound because" | |
| 195 + " certificate authentication is still pending.", | |
| 196 + SSL_GETPID(), ss->fd)); | |
| 197 ss->ssl3.hs.restartTarget = ssl3_SendClientSecondRound; | |
| 198 return SECWouldBlock; | |
| 199 } | |
| 200 @@ -7500,20 +7539,59 @@ | |
| 201 goto loser; /* err code was set. */ | |
| 202 } | |
| 203 | |
| 204 - /* XXX: If the server's certificate hasn't been authenticated by this | |
| 205 - * point, then we may be leaking this NPN message to an attacker. | |
| 206 + /* This must be done after we've set ss->ssl3.cwSpec in | |
| 207 + * ssl3_SendChangeCipherSpecs because SSL_GetChannelInfo uses information | |
| 208 + * from cwSpec. This must be done before we call ssl3_CheckFalseStart | |
| 209 + * because the false start callback (if any) may need the information from | |
| 210 + * the functions that depend on this being set. | |
| 211 */ | |
| 212 + ss->enoughFirstHsDone = PR_TRUE; | |
| 213 + | |
| 214 if (!ss->firstHsDone) { | |
| 215 + /* XXX: If the server's certificate hasn't been authenticated by this | |
| 216 + * point, then we may be leaking this NPN message to an attacker. | |
| 217 + */ | |
| 218 rv = ssl3_SendNextProto(ss); | |
| 219 if (rv != SECSuccess) { | |
| 220 goto loser; /* err code was set. */ | |
| 221 } | |
| 222 } | |
| 223 + | |
| 224 rv = ssl3_SendEncryptedExtensions(ss); | |
| 225 if (rv != SECSuccess) { | |
| 226 goto loser; /* err code was set. */ | |
| 227 } | |
| 228 | |
| 229 + if (!ss->firstHsDone) { | |
| 230 + if (ss->opt.enableFalseStart) { | |
| 231 + if (!ss->ssl3.hs.authCertificatePending) { | |
| 232 + /* When we fix bug 589047, we will need to know whether we are | |
| 233 + * false starting before we try to flush the client second | |
| 234 + * round to the network. With that in mind, we purposefully | |
| 235 + * call ssl3_CheckFalseStart before calling ssl3_SendFinished, | |
| 236 + * which includes a call to ssl3_FlushHandshake, so that | |
| 237 + * no application develops a reliance on such flushing being | |
| 238 + * done before its false start callback is called. | |
| 239 + */ | |
| 240 + ssl_ReleaseXmitBufLock(ss); | |
| 241 + rv = ssl3_CheckFalseStart(ss); | |
| 242 + ssl_GetXmitBufLock(ss); | |
| 243 + if (rv != SECSuccess) { | |
| 244 + goto loser; | |
| 245 + } | |
| 246 + } else { | |
| 247 + /* The certificate authentication and the server's Finished | |
| 248 + * message are racing each other. If the certificate | |
| 249 + * authentication wins, then we will try to false start in | |
| 250 + * ssl3_AuthCertificateComplete. | |
| 251 + */ | |
| 252 + SSL_TRC(3, ("%d: SSL3[%p]: deferring false start check because" | |
| 253 + " certificate authentication is still pending.", | |
| 254 + SSL_GETPID(), ss->fd)); | |
| 255 + } | |
| 256 + } | |
| 257 + } | |
| 258 + | |
| 259 rv = ssl3_SendFinished(ss, 0); | |
| 260 if (rv != SECSuccess) { | |
| 261 goto loser; /* err code was set. */ | |
| 262 @@ -7526,10 +7604,7 @@ | |
| 263 else | |
| 264 ss->ssl3.hs.ws = wait_change_cipher; | |
| 265 | |
| 266 - /* Do the handshake callback for sslv3 here, if we can false start. */ | |
| 267 - if (ss->handshakeCallback != NULL && ssl3_CanFalseStart(ss)) { | |
| 268 - (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData); | |
| 269 - } | |
| 270 + PORT_Assert(ssl3_WaitingForStartOfServerSecondRound(ss)); | |
| 271 | |
| 272 return SECSuccess; | |
| 273 | |
| 274 @@ -10147,13 +10222,6 @@ | |
| 275 | |
| 276 ss->ssl3.hs.authCertificatePending = PR_TRUE; | |
| 277 rv = SECSuccess; | |
| 278 - | |
| 279 - /* XXX: Async cert validation and False Start don't work together | |
| 280 - * safely yet; if we leave False Start enabled, we may end up false | |
| 281 - * starting (sending application data) before we | |
| 282 - * SSL_AuthCertificateComplete has been called. | |
| 283 - */ | |
| 284 - ss->opt.enableFalseStart = PR_FALSE; | |
| 285 } | |
| 286 | |
| 287 if (rv != SECSuccess) { | |
| 288 @@ -10278,6 +10346,12 @@ | |
| 289 } else if (ss->ssl3.hs.restartTarget != NULL) { | |
| 290 sslRestartTarget target = ss->ssl3.hs.restartTarget; | |
| 291 ss->ssl3.hs.restartTarget = NULL; | |
| 292 + | |
| 293 + if (target == ssl3_FinishHandshake) { | |
| 294 + SSL_TRC(3,("%d: SSL3[%p]: certificate authentication lost the race" | |
| 295 + " with peer's finished message", SSL_GETPID(), ss->fd)); | |
| 296 + } | |
| 297 + | |
| 298 rv = target(ss); | |
| 299 /* Even if we blocked here, we have accomplished enough to claim | |
| 300 * success. Any remaining work will be taken care of by subsequent | |
| 301 @@ -10287,7 +10361,27 @@ | |
| 302 rv = SECSuccess; | |
| 303 } | |
| 304 } else { | |
| 305 - rv = SECSuccess; | |
| 306 + SSL_TRC(3, ("%d: SSL3[%p]: certificate authentication won the race with" | |
| 307 + " peer's finished message", SSL_GETPID(), ss->fd)); | |
| 308 + | |
| 309 + PORT_Assert(!ss->firstHsDone); | |
| 310 + PORT_Assert(!ss->sec.isServer); | |
| 311 + PORT_Assert(!ss->ssl3.hs.isResuming); | |
| 312 + PORT_Assert(ss->ssl3.hs.ws != idle_handshake); | |
| 313 + | |
| 314 + if (ss->opt.enableFalseStart && | |
| 315 + !ss->firstHsDone && | |
| 316 + !ss->sec.isServer && | |
| 317 + !ss->ssl3.hs.isResuming && | |
| 318 + ssl3_WaitingForStartOfServerSecondRound(ss)) { | |
| 319 + /* ssl3_SendClientSecondRound deferred the false start check because | |
| 320 + * certificate authentication was pending, so we do it now if we sti
ll | |
| 321 + * haven't received any of the server's second round yet. | |
| 322 + */ | |
| 323 + rv = ssl3_CheckFalseStart(ss); | |
| 324 + } else { | |
| 325 + rv = SECSuccess; | |
| 326 + } | |
| 327 } | |
| 328 | |
| 329 done: | |
| 330 @@ -10913,9 +11007,6 @@ | |
| 331 return rv; | |
| 332 } | |
| 333 | |
| 334 - ss->gs.writeOffset = 0; | |
| 335 - ss->gs.readOffset = 0; | |
| 336 - | |
| 337 if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) { | |
| 338 effectiveExchKeyType = kt_rsa; | |
| 339 } else { | |
| 340 @@ -10980,6 +11071,9 @@ | |
| 341 return rv; | |
| 342 } | |
| 343 | |
| 344 +/* The return type is SECStatus instead of void because this function needs | |
| 345 + * to have type sslRestartTarget. | |
| 346 + */ | |
| 347 SECStatus | |
| 348 ssl3_FinishHandshake(sslSocket * ss) | |
| 349 { | |
| 350 @@ -10989,19 +11083,16 @@ | |
| 351 | |
| 352 /* The first handshake is now completed. */ | |
| 353 ss->handshake = NULL; | |
| 354 - ss->firstHsDone = PR_TRUE; | |
| 355 | |
| 356 if (ss->ssl3.hs.cacheSID) { | |
| 357 (*ss->sec.cache)(ss->sec.ci.sid); | |
| 358 ss->ssl3.hs.cacheSID = PR_FALSE; | |
| 359 } | |
| 360 | |
| 361 + ss->ssl3.hs.canFalseStart = PR_FALSE; /* False Start phase is complete */ | |
| 362 ss->ssl3.hs.ws = idle_handshake; | |
| 363 | |
| 364 - /* Do the handshake callback for sslv3 here, if we cannot false start. */ | |
| 365 - if (ss->handshakeCallback != NULL && !ssl3_CanFalseStart(ss)) { | |
| 366 - (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData); | |
| 367 - } | |
| 368 + ssl_FinishHandshake(ss); | |
| 369 | |
| 370 return SECSuccess; | |
| 371 } | |
| 372 @@ -11966,7 +12057,6 @@ | |
| 373 | |
| 374 ssl_ReleaseSSL3HandshakeLock(ss); | |
| 375 return rv; | |
| 376 - | |
| 377 } | |
| 378 | |
| 379 /* | |
| 380 Index: net/third_party/nss/ssl/ssl3gthr.c | |
| 381 =================================================================== | |
| 382 --- net/third_party/nss/ssl/ssl3gthr.c (revision 227672) | |
| 383 +++ net/third_party/nss/ssl/ssl3gthr.c (working copy) | |
| 384 @@ -275,11 +275,17 @@ | |
| 385 { | |
| 386 SSL3Ciphertext cText; | |
| 387 int rv; | |
| 388 - PRBool canFalseStart = PR_FALSE; | |
| 389 + PRBool keepGoing = PR_TRUE; | |
| 390 | |
| 391 SSL_TRC(30, ("ssl3_GatherCompleteHandshake")); | |
| 392 | |
| 393 + /* ssl3_HandleRecord may end up eventually calling ssl_FinishHandshake, | |
| 394 + * which requires the 1stHandshakeLock, which must be acquired before the | |
| 395 + * RecvBufLock. | |
| 396 + */ | |
| 397 + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 398 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); | |
| 399 + | |
| 400 do { | |
| 401 PRBool handleRecordNow = PR_FALSE; | |
| 402 | |
| 403 @@ -364,24 +370,52 @@ | |
| 404 | |
| 405 cText.buf = &ss->gs.inbuf; | |
| 406 rv = ssl3_HandleRecord(ss, &cText, &ss->gs.buf); | |
| 407 + | |
| 408 + if (rv == (int) SECSuccess && ss->gs.buf.len > 0) { | |
| 409 + /* We have application data to return to the application. This | |
| 410 + * prioritizes returning application data to the application ove
r | |
| 411 + * completing any renegotiation handshake we may be doing. | |
| 412 + */ | |
| 413 + PORT_Assert(ss->firstHsDone); | |
| 414 + PORT_Assert(cText.type == content_application_data); | |
| 415 + break; | |
| 416 + } | |
| 417 } | |
| 418 if (rv < 0) { | |
| 419 return ss->recvdCloseNotify ? 0 : rv; | |
| 420 } | |
| 421 | |
| 422 - /* If we kicked off a false start in ssl3_HandleServerHelloDone, break | |
| 423 - * out of this loop early without finishing the handshake. | |
| 424 - */ | |
| 425 - if (ss->opt.enableFalseStart) { | |
| 426 - ssl_GetSSL3HandshakeLock(ss); | |
| 427 - canFalseStart = (ss->ssl3.hs.ws == wait_change_cipher || | |
| 428 - ss->ssl3.hs.ws == wait_new_session_ticket) && | |
| 429 - ssl3_CanFalseStart(ss); | |
| 430 - ssl_ReleaseSSL3HandshakeLock(ss); | |
| 431 + PORT_Assert(keepGoing); | |
| 432 + ssl_GetSSL3HandshakeLock(ss); | |
| 433 + if (ss->ssl3.hs.ws == idle_handshake) { | |
| 434 + /* We are done with the current handshake so stop trying to | |
| 435 + * handshake. Note that it would be safe to test ss->firstHsDone | |
| 436 + * instead of ss->ssl3.hs.ws. By testing ss->ssl3.hs.ws instead, | |
| 437 + * we prioritize completing a renegotiation handshake over sending | |
| 438 + * application data. | |
| 439 + */ | |
| 440 + PORT_Assert(ss->firstHsDone); | |
| 441 + PORT_Assert(!ss->ssl3.hs.canFalseStart); | |
| 442 + keepGoing = PR_FALSE; | |
| 443 + } else if (ss->ssl3.hs.canFalseStart) { | |
| 444 + /* Prioritize sending application data over trying to complete | |
| 445 + * the handshake if we're false starting. | |
| 446 + * | |
| 447 + * If we were to do this check at the beginning of the loop instead | |
| 448 + * of here, then this function would become be a no-op after | |
| 449 + * receiving the ServerHelloDone in the false start case, and we | |
| 450 + * would never complete the handshake. | |
| 451 + */ | |
| 452 + PORT_Assert(!ss->firstHsDone); | |
| 453 + | |
| 454 + if (ssl3_WaitingForStartOfServerSecondRound(ss)) { | |
| 455 + keepGoing = PR_FALSE; | |
| 456 + } else { | |
| 457 + ss->ssl3.hs.canFalseStart = PR_FALSE; | |
| 458 + } | |
| 459 } | |
| 460 - } while (ss->ssl3.hs.ws != idle_handshake && | |
| 461 - !canFalseStart && | |
| 462 - ss->gs.buf.len == 0); | |
| 463 + ssl_ReleaseSSL3HandshakeLock(ss); | |
| 464 + } while (keepGoing); | |
| 465 | |
| 466 ss->gs.readOffset = 0; | |
| 467 ss->gs.writeOffset = ss->gs.buf.len; | |
| 468 @@ -404,7 +438,10 @@ | |
| 469 { | |
| 470 int rv; | |
| 471 | |
| 472 + /* ssl3_GatherCompleteHandshake requires both of these locks. */ | |
| 473 + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 474 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); | |
| 475 + | |
| 476 do { | |
| 477 rv = ssl3_GatherCompleteHandshake(ss, flags); | |
| 478 } while (rv > 0 && ss->gs.buf.len == 0); | |
| 479 Index: net/third_party/nss/ssl/sslauth.c | |
| 480 =================================================================== | |
| 481 --- net/third_party/nss/ssl/sslauth.c (revision 227672) | |
| 482 +++ net/third_party/nss/ssl/sslauth.c (working copy) | |
| 483 @@ -100,7 +100,6 @@ | |
| 484 sslSocket *ss; | |
| 485 const char *cipherName; | |
| 486 PRBool isDes = PR_FALSE; | |
| 487 - PRBool enoughFirstHsDone = PR_FALSE; | |
| 488 | |
| 489 ss = ssl_FindSocket(fd); | |
| 490 if (!ss) { | |
| 491 @@ -118,14 +117,7 @@ | |
| 492 *op = SSL_SECURITY_STATUS_OFF; | |
| 493 } | |
| 494 | |
| 495 - if (ss->firstHsDone) { | |
| 496 - enoughFirstHsDone = PR_TRUE; | |
| 497 - } else if (ss->version >= SSL_LIBRARY_VERSION_3_0 && | |
| 498 - ssl3_CanFalseStart(ss)) { | |
| 499 - enoughFirstHsDone = PR_TRUE; | |
| 500 - } | |
| 501 - | |
| 502 - if (ss->opt.useSecurity && enoughFirstHsDone) { | |
| 503 + if (ss->opt.useSecurity && ss->enoughFirstHsDone) { | |
| 504 if (ss->version < SSL_LIBRARY_VERSION_3_0) { | |
| 505 cipherName = ssl_cipherName[ss->sec.cipherType]; | |
| 506 } else { | |
| 507 Index: net/third_party/nss/ssl/sslimpl.h | |
| 508 =================================================================== | |
| 509 --- net/third_party/nss/ssl/sslimpl.h (revision 227672) | |
| 510 +++ net/third_party/nss/ssl/sslimpl.h (working copy) | |
| 511 @@ -881,6 +881,8 @@ | |
| 512 /* Shared state between ssl3_HandleFinished and ssl3_FinishHandshake */ | |
| 513 PRBool cacheSID; | |
| 514 | |
| 515 + PRBool canFalseStart; /* Can/did we False Start */ | |
| 516 + | |
| 517 /* clientSigAndHash contains the contents of the signature_algorithms | |
| 518 * extension (if any) from the client. This is only valid for TLS 1.2 | |
| 519 * or later. */ | |
| 520 @@ -1162,6 +1164,10 @@ | |
| 521 unsigned long clientAuthRequested; | |
| 522 unsigned long delayDisabled; /* Nagle delay disabled */ | |
| 523 unsigned long firstHsDone; /* first handshake is complete. */ | |
| 524 + unsigned long enoughFirstHsDone; /* enough of the first handshake is | |
| 525 + * done for callbacks to be able to | |
| 526 + * retrieve channel security | |
| 527 + * parameters from the SSL socket. */ | |
| 528 unsigned long handshakeBegun; | |
| 529 unsigned long lastWriteBlocked; | |
| 530 unsigned long recvdCloseNotify; /* received SSL EOF. */ | |
| 531 @@ -1210,6 +1216,8 @@ | |
| 532 void *badCertArg; | |
| 533 SSLHandshakeCallback handshakeCallback; | |
| 534 void *handshakeCallbackData; | |
| 535 + SSLCanFalseStartCallback canFalseStartCallback; | |
| 536 + void *canFalseStartCallbackData; | |
| 537 void *pkcs11PinArg; | |
| 538 SSLNextProtoCallback nextProtoCallback; | |
| 539 void *nextProtoArg; | |
| 540 @@ -1423,7 +1431,19 @@ | |
| 541 | |
| 542 extern SECStatus ssl_EnableNagleDelay(sslSocket *ss, PRBool enabled); | |
| 543 | |
| 544 -extern PRBool ssl3_CanFalseStart(sslSocket *ss); | |
| 545 +extern void ssl_FinishHandshake(sslSocket *ss); | |
| 546 + | |
| 547 +/* Returns PR_TRUE if we are still waiting for the server to respond to our | |
| 548 + * client second round. Once we've received any part of the server's second | |
| 549 + * round then we don't bother trying to false start since it is almost always | |
| 550 + * the case that the NewSessionTicket, ChangeCipherSoec, and Finished messages | |
| 551 + * were sent in the same packet and we want to process them all at the same | |
| 552 + * time. If we were to try to false start in the middle of the server's second | |
| 553 + * round, then we would increase the number of I/O operations | |
| 554 + * (SSL_ForceHandshake/PR_Recv/PR_Send/etc.) needed to finish the handshake. | |
| 555 + */ | |
| 556 +extern PRBool ssl3_WaitingForStartOfServerSecondRound(sslSocket *ss); | |
| 557 + | |
| 558 extern SECStatus | |
| 559 ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec, | |
| 560 PRBool isServer, | |
| 561 Index: net/third_party/nss/ssl/sslinfo.c | |
| 562 =================================================================== | |
| 563 --- net/third_party/nss/ssl/sslinfo.c (revision 227672) | |
| 564 +++ net/third_party/nss/ssl/sslinfo.c (working copy) | |
| 565 @@ -26,7 +26,6 @@ | |
| 566 sslSocket * ss; | |
| 567 SSLChannelInfo inf; | |
| 568 sslSessionID * sid; | |
| 569 - PRBool enoughFirstHsDone = PR_FALSE; | |
| 570 | |
| 571 if (!info || len < sizeof inf.length) { | |
| 572 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 573 @@ -43,14 +42,7 @@ | |
| 574 memset(&inf, 0, sizeof inf); | |
| 575 inf.length = PR_MIN(sizeof inf, len); | |
| 576 | |
| 577 - if (ss->firstHsDone) { | |
| 578 - enoughFirstHsDone = PR_TRUE; | |
| 579 - } else if (ss->version >= SSL_LIBRARY_VERSION_3_0 && | |
| 580 - ssl3_CanFalseStart(ss)) { | |
| 581 - enoughFirstHsDone = PR_TRUE; | |
| 582 - } | |
| 583 - | |
| 584 - if (ss->opt.useSecurity && enoughFirstHsDone) { | |
| 585 + if (ss->opt.useSecurity && ss->enoughFirstHsDone) { | |
| 586 sid = ss->sec.ci.sid; | |
| 587 inf.protocolVersion = ss->version; | |
| 588 inf.authKeyBits = ss->sec.authKeyBits; | |
| 589 Index: net/third_party/nss/ssl/sslsecur.c | |
| 590 =================================================================== | |
| 591 --- net/third_party/nss/ssl/sslsecur.c (revision 227672) | |
| 592 +++ net/third_party/nss/ssl/sslsecur.c (working copy) | |
| 593 @@ -97,23 +97,13 @@ | |
| 594 ss->securityHandshake = 0; | |
| 595 } | |
| 596 if (ss->handshake == 0) { | |
| 597 - ssl_GetRecvBufLock(ss); | |
| 598 - ss->gs.recordLen = 0; | |
| 599 - ssl_ReleaseRecvBufLock(ss); | |
| 600 - | |
| 601 - SSL_TRC(3, ("%d: SSL[%d]: handshake is completed", | |
| 602 - SSL_GETPID(), ss->fd)); | |
| 603 - /* call handshake callback for ssl v2 */ | |
| 604 - /* for v3 this is done in ssl3_HandleFinished() */ | |
| 605 - if ((ss->handshakeCallback != NULL) && /* has callback */ | |
| 606 - (!ss->firstHsDone) && /* only first time */ | |
| 607 - (ss->version < SSL_LIBRARY_VERSION_3_0)) { /* not ssl3 */ | |
| 608 - ss->firstHsDone = PR_TRUE; | |
| 609 - (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData); | |
| 610 + /* for v3 this is done in ssl3_FinishHandshake */ | |
| 611 + if (!ss->firstHsDone && ss->version < SSL_LIBRARY_VERSION_3_0) { | |
| 612 + ssl_GetRecvBufLock(ss); | |
| 613 + ss->gs.recordLen = 0; | |
| 614 + ssl_FinishHandshake(ss); | |
| 615 + ssl_ReleaseRecvBufLock(ss); | |
| 616 } | |
| 617 - ss->firstHsDone = PR_TRUE; | |
| 618 - ss->gs.writeOffset = 0; | |
| 619 - ss->gs.readOffset = 0; | |
| 620 break; | |
| 621 } | |
| 622 rv = (*ss->handshake)(ss); | |
| 623 @@ -134,6 +124,24 @@ | |
| 624 return rv; | |
| 625 } | |
| 626 | |
| 627 +void | |
| 628 +ssl_FinishHandshake(sslSocket *ss) | |
| 629 +{ | |
| 630 + PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | |
| 631 + PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); | |
| 632 + | |
| 633 + SSL_TRC(3, ("%d: SSL[%d]: handshake is completed", SSL_GETPID(), ss->fd)); | |
| 634 + | |
| 635 + ss->firstHsDone = PR_TRUE; | |
| 636 + ss->enoughFirstHsDone = PR_TRUE; | |
| 637 + ss->gs.writeOffset = 0; | |
| 638 + ss->gs.readOffset = 0; | |
| 639 + | |
| 640 + if (ss->handshakeCallback) { | |
| 641 + (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData); | |
| 642 + } | |
| 643 +} | |
| 644 + | |
| 645 /* | |
| 646 * Handshake function that blocks. Used to force a | |
| 647 * retry on a connection on the next read/write. | |
| 648 @@ -206,6 +214,7 @@ | |
| 649 ssl_Get1stHandshakeLock(ss); | |
| 650 | |
| 651 ss->firstHsDone = PR_FALSE; | |
| 652 + ss->enoughFirstHsDone = PR_FALSE; | |
| 653 if ( asServer ) { | |
| 654 ss->handshake = ssl2_BeginServerHandshake; | |
| 655 ss->handshaking = sslHandshakingAsServer; | |
| 656 @@ -221,6 +230,8 @@ | |
| 657 ssl_ReleaseRecvBufLock(ss); | |
| 658 | |
| 659 ssl_GetSSL3HandshakeLock(ss); | |
| 660 + ss->ssl3.hs.canFalseStart = PR_FALSE; | |
| 661 + ss->ssl3.hs.restartTarget = NULL; | |
| 662 | |
| 663 /* | |
| 664 ** Blow away old security state and get a fresh setup. | |
| 665 @@ -331,6 +342,71 @@ | |
| 666 return SECSuccess; | |
| 667 } | |
| 668 | |
| 669 +/* Register an application callback to be called when false start may happen. | |
| 670 +** Acquires and releases HandshakeLock. | |
| 671 +*/ | |
| 672 +SECStatus | |
| 673 +SSL_SetCanFalseStartCallback(PRFileDesc *fd, SSLCanFalseStartCallback cb, | |
| 674 + void *arg) | |
| 675 +{ | |
| 676 + sslSocket *ss; | |
| 677 + | |
| 678 + ss = ssl_FindSocket(fd); | |
| 679 + if (!ss) { | |
| 680 + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetCanFalseStartCallback", | |
| 681 + SSL_GETPID(), fd)); | |
| 682 + return SECFailure; | |
| 683 + } | |
| 684 + | |
| 685 + if (!ss->opt.useSecurity) { | |
| 686 + PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 687 + return SECFailure; | |
| 688 + } | |
| 689 + | |
| 690 + ssl_Get1stHandshakeLock(ss); | |
| 691 + ssl_GetSSL3HandshakeLock(ss); | |
| 692 + | |
| 693 + ss->canFalseStartCallback = cb; | |
| 694 + ss->canFalseStartCallbackData = arg; | |
| 695 + | |
| 696 + ssl_ReleaseSSL3HandshakeLock(ss); | |
| 697 + ssl_Release1stHandshakeLock(ss); | |
| 698 + | |
| 699 + return SECSuccess; | |
| 700 +} | |
| 701 + | |
| 702 +SECStatus | |
| 703 +SSL_RecommendedCanFalseStart(PRFileDesc *fd, PRBool *canFalseStart) | |
| 704 +{ | |
| 705 + sslSocket *ss; | |
| 706 + | |
| 707 + *canFalseStart = PR_FALSE; | |
| 708 + ss = ssl_FindSocket(fd); | |
| 709 + if (!ss) { | |
| 710 + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_RecommendedCanFalseStart", | |
| 711 + SSL_GETPID(), fd)); | |
| 712 + return SECFailure; | |
| 713 + } | |
| 714 + | |
| 715 + if (!ss->ssl3.initialized) { | |
| 716 + PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 717 + return SECFailure; | |
| 718 + } | |
| 719 + | |
| 720 + if (ss->version < SSL_LIBRARY_VERSION_3_0) { | |
| 721 + PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2); | |
| 722 + return SECFailure; | |
| 723 + } | |
| 724 + | |
| 725 + /* Require a forward-secret key exchange. */ | |
| 726 + *canFalseStart = ss->ssl3.hs.kea_def->kea == kea_dhe_dss || | |
| 727 + ss->ssl3.hs.kea_def->kea == kea_dhe_rsa || | |
| 728 + ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa || | |
| 729 + ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa; | |
| 730 + | |
| 731 + return SECSuccess; | |
| 732 +} | |
| 733 + | |
| 734 /* Try to make progress on an SSL handshake by attempting to read the | |
| 735 ** next handshake from the peer, and sending any responses. | |
| 736 ** For non-blocking sockets, returns PR_ERROR_WOULD_BLOCK if it cannot | |
| 737 @@ -524,6 +600,9 @@ | |
| 738 int amount; | |
| 739 int available; | |
| 740 | |
| 741 + /* ssl3_GatherAppDataRecord may call ssl_FinishHandshake, which needs the | |
| 742 + * 1stHandshakeLock. */ | |
| 743 + ssl_Get1stHandshakeLock(ss); | |
| 744 ssl_GetRecvBufLock(ss); | |
| 745 | |
| 746 available = ss->gs.writeOffset - ss->gs.readOffset; | |
| 747 @@ -590,6 +669,7 @@ | |
| 748 | |
| 749 done: | |
| 750 ssl_ReleaseRecvBufLock(ss); | |
| 751 + ssl_Release1stHandshakeLock(ss); | |
| 752 return rv; | |
| 753 } | |
| 754 | |
| 755 @@ -1156,7 +1236,8 @@ | |
| 756 int | |
| 757 ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags) | |
| 758 { | |
| 759 - int rv = 0; | |
| 760 + int rv = 0; | |
| 761 + PRBool falseStart = PR_FALSE; | |
| 762 | |
| 763 SSL_TRC(2, ("%d: SSL[%d]: SecureSend: sending %d bytes", | |
| 764 SSL_GETPID(), ss->fd, len)); | |
| 765 @@ -1191,19 +1272,14 @@ | |
| 766 ss->writerThread = PR_GetCurrentThread(); | |
| 767 /* If any of these is non-zero, the initial handshake is not done. */ | |
| 768 if (!ss->firstHsDone) { | |
| 769 - PRBool canFalseStart = PR_FALSE; | |
| 770 ssl_Get1stHandshakeLock(ss); | |
| 771 - if (ss->version >= SSL_LIBRARY_VERSION_3_0) { | |
| 772 + if (ss->opt.enableFalseStart && | |
| 773 + ss->version >= SSL_LIBRARY_VERSION_3_0) { | |
| 774 ssl_GetSSL3HandshakeLock(ss); | |
| 775 - if ((ss->ssl3.hs.ws == wait_change_cipher || | |
| 776 - ss->ssl3.hs.ws == wait_finished || | |
| 777 - ss->ssl3.hs.ws == wait_new_session_ticket) && | |
| 778 - ssl3_CanFalseStart(ss)) { | |
| 779 - canFalseStart = PR_TRUE; | |
| 780 - } | |
| 781 + falseStart = ss->ssl3.hs.canFalseStart; | |
| 782 ssl_ReleaseSSL3HandshakeLock(ss); | |
| 783 } | |
| 784 - if (!canFalseStart && | |
| 785 + if (!falseStart && | |
| 786 (ss->handshake || ss->nextHandshake || ss->securityHandshake)) { | |
| 787 rv = ssl_Do1stHandshake(ss); | |
| 788 } | |
| 789 @@ -1228,6 +1304,17 @@ | |
| 790 goto done; | |
| 791 } | |
| 792 | |
| 793 + if (!ss->firstHsDone) { | |
| 794 + PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_3_0); | |
| 795 +#ifdef DEBUG | |
| 796 + ssl_GetSSL3HandshakeLock(ss); | |
| 797 + PORT_Assert(ss->ssl3.hs.canFalseStart); | |
| 798 + ssl_ReleaseSSL3HandshakeLock(ss); | |
| 799 +#endif | |
| 800 + SSL_TRC(3, ("%d: SSL[%d]: SecureSend: sending data due to false start", | |
| 801 + SSL_GETPID(), ss->fd)); | |
| 802 + } | |
| 803 + | |
| 804 /* Send out the data using one of these functions: | |
| 805 * ssl2_SendClear, ssl2_SendStream, ssl2_SendBlock, | |
| 806 * ssl3_SendApplicationData | |
| 807 Index: net/third_party/nss/ssl/sslsock.c | |
| 808 =================================================================== | |
| 809 --- net/third_party/nss/ssl/sslsock.c (revision 227672) | |
| 810 +++ net/third_party/nss/ssl/sslsock.c (working copy) | |
| 811 @@ -366,6 +366,8 @@ | |
| 812 ss->badCertArg = os->badCertArg; | |
| 813 ss->handshakeCallback = os->handshakeCallback; | |
| 814 ss->handshakeCallbackData = os->handshakeCallbackData; | |
| 815 + ss->canFalseStartCallback = os->canFalseStartCallback; | |
| 816 + ss->canFalseStartCallbackData = os->canFalseStartCallbackData; | |
| 817 ss->pkcs11PinArg = os->pkcs11PinArg; | |
| 818 ss->getChannelID = os->getChannelID; | |
| 819 ss->getChannelIDArg = os->getChannelIDArg; | |
| 820 @@ -2457,10 +2459,14 @@ | |
| 821 } else if (new_flags & PR_POLL_WRITE) { | |
| 822 /* The caller is trying to write, but the handshake is | |
| 823 ** blocked waiting for data to read, and the first | |
| 824 - ** handshake has been sent. so do NOT to poll on write. | |
| 825 + ** handshake has been sent. So do NOT to poll on write | |
| 826 + ** unless we did false start. | |
| 827 */ | |
| 828 - new_flags ^= PR_POLL_WRITE; /* don't select on write. */ | |
| 829 - new_flags |= PR_POLL_READ; /* do select on read. */ | |
| 830 + if (!(ss->version >= SSL_LIBRARY_VERSION_3_0 && | |
| 831 + ss->ssl3.hs.canFalseStart)) { | |
| 832 + new_flags ^= PR_POLL_WRITE; /* don't select on write. */ | |
| 833 + } | |
| 834 + new_flags |= PR_POLL_READ; /* do select on read. */ | |
| 835 } | |
| 836 } | |
| 837 } else if ((new_flags & PR_POLL_READ) && (SSL_DataPending(fd) > 0)) { | |
| OLD | NEW |