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 |