Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(336)

Side by Side Diff: net/third_party/nss/patches/snapstart.patch

Issue 7003069: Remove the TLS Snap Start code from NSS. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 diff --git a/mozilla/security/nss/lib/ssl/fnv1a64.c b/mozilla/security/nss/lib/s sl/fnv1a64.c
2 new file mode 100644
3 index 0000000..c7c4b08
4 --- /dev/null
5 +++ b/mozilla/security/nss/lib/ssl/fnv1a64.c
6 @@ -0,0 +1,72 @@
7 +/*
8 + * FNV1A64 Hash
9 + * http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param
10 + *
11 + * ***** BEGIN LICENSE BLOCK *****
12 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
13 + *
14 + * The contents of this file are subject to the Mozilla Public License Version
15 + * 1.1 (the "License"); you may not use this file except in compliance with
16 + * the License. You may obtain a copy of the License at
17 + * http://www.mozilla.org/MPL/
18 + *
19 + * Software distributed under the License is distributed on an "AS IS" basis,
20 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
21 + * for the specific language governing rights and limitations under the
22 + * License.
23 + *
24 + * The Original Code is the Netscape security libraries.
25 + *
26 + * The Initial Developer of the Original Code is
27 + * Netscape Communications Corporation.
28 + * Portions created by the Initial Developer are Copyright (C) 1994-2000
29 + * the Initial Developer. All Rights Reserved.
30 + *
31 + * Contributor(s):
32 + * Adam Langley, Google Inc.
33 + *
34 + * Alternatively, the contents of this file may be used under the terms of
35 + * either the GNU General Public License Version 2 or later (the "GPL"), or
36 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
37 + * in which case the provisions of the GPL or the LGPL are applicable instead
38 + * of those above. If you wish to allow use of your version of this file only
39 + * under the terms of either the GPL or the LGPL, and not to allow others to
40 + * use your version of this file under the terms of the MPL, indicate your
41 + * decision by deleting the provisions above and replace them with the notice
42 + * and other provisions required by the GPL or the LGPL. If you do not delete
43 + * the provisions above, a recipient may use your version of this file under
44 + * the terms of any one of the MPL, the GPL or the LGPL.
45 + *
46 + * ***** END LICENSE BLOCK ***** */
47 +
48 +/* $Id: fnv1a64.c,v 1.0 2010/08/09 13:00:00 agl%google.com Exp $ */
49 +
50 +#include "prtypes.h"
51 +#include "prnetdb.h"
52 +
53 +/* Older versions of Visual C++ don't support the 'ull' suffix. */
54 +#ifdef _MSC_VER
55 +static const PRUint64 FNV1A64_OFFSET_BASIS = 14695981039346656037ui64;
56 +static const PRUint64 FNV1A64_PRIME = 1099511628211ui64;
57 +#else
58 +static const PRUint64 FNV1A64_OFFSET_BASIS = 14695981039346656037ull;
59 +static const PRUint64 FNV1A64_PRIME = 1099511628211ull;
60 +#endif
61 +
62 +void FNV1A64_Init(PRUint64* digest) {
63 + *digest = FNV1A64_OFFSET_BASIS;
64 +}
65 +
66 +void FNV1A64_Update(PRUint64* digest, const unsigned char *data,
67 + unsigned int length) {
68 + unsigned int i;
69 +
70 + for (i = 0; i < length; i++) {
71 + *digest ^= data[i];
72 + *digest *= FNV1A64_PRIME;
73 + }
74 +}
75 +
76 +void FNV1A64_Final(PRUint64 *digest) {
77 + *digest = PR_htonll(*digest);
78 +}
79 diff --git a/mozilla/security/nss/lib/ssl/snapstart.c b/mozilla/security/nss/lib /ssl/snapstart.c
80 new file mode 100644
81 index 0000000..ca2cafa
82 --- /dev/null
83 +++ b/mozilla/security/nss/lib/ssl/snapstart.c
84 @@ -0,0 +1,1062 @@
85 +/*
86 + * TLS Snap Start
87 + *
88 + * ***** BEGIN LICENSE BLOCK *****
89 + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
90 + *
91 + * The contents of this file are subject to the Mozilla Public License Version
92 + * 1.1 (the "License"); you may not use this file except in compliance with
93 + * the License. You may obtain a copy of the License at
94 + * http://www.mozilla.org/MPL/
95 + *
96 + * Software distributed under the License is distributed on an "AS IS" basis,
97 + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
98 + * for the specific language governing rights and limitations under the
99 + * License.
100 + *
101 + * The Original Code is the Netscape security libraries.
102 + *
103 + * The Initial Developer of the Original Code is
104 + * Netscape Communications Corporation.
105 + * Portions created by the Initial Developer are Copyright (C) 1994-2000
106 + * the Initial Developer. All Rights Reserved.
107 + *
108 + * Contributor(s):
109 + * Adam Langley, Google Inc.
110 + *
111 + * Alternatively, the contents of this file may be used under the terms of
112 + * either the GNU General Public License Version 2 or later (the "GPL"), or
113 + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
114 + * in which case the provisions of the GPL or the LGPL are applicable instead
115 + * of those above. If you wish to allow use of your version of this file only
116 + * under the terms of either the GPL or the LGPL, and not to allow others to
117 + * use your version of this file under the terms of the MPL, indicate your
118 + * decision by deleting the provisions above and replace them with the notice
119 + * and other provisions required by the GPL or the LGPL. If you do not delete
120 + * the provisions above, a recipient may use your version of this file under
121 + * the terms of any one of the MPL, the GPL or the LGPL.
122 + *
123 + * ***** END LICENSE BLOCK ***** */
124 +
125 +/* $Id: ssl3snap.c,v 1.0 2010/08/09 13:00:00 agl%google.com Exp $ */
126 +
127 +
128 +/* TODO(agl): Refactor ssl3_CompressMACEncryptRecord so that it can write to
129 +** |sendBuf| directly and fix ssl3_AppendSnapStartHandshakeRecord and
130 +** ssl3_AppendSnapStartApplicationData.
131 +*/
132 +
133 +/* TODO(agl): Add support for snap starting with compression. */
134 +
135 +/* TODO(agl): Free snapStartApplicationData as soon as the handshake has
136 +** completed.
137 +*/
138 +
139 +#include "pk11pub.h"
140 +#include "ssl.h"
141 +#include "sslimpl.h"
142 +#include "sslproto.h"
143 +
144 +static unsigned int GetBE16(const void *in)
145 +{
146 + const unsigned char *p = in;
147 + return ((unsigned) p[0]) << 8 |
148 + p[1];
149 +}
150 +
151 +static unsigned int GetBE24(const void *in)
152 +{
153 + const unsigned char *p = in;
154 + return ((unsigned) p[0]) << 16 |
155 + ((unsigned) p[1]) << 8 |
156 + p[2];
157 +}
158 +
159 +static void PutBE16(void *out, unsigned int value)
160 +{
161 + unsigned char *p = out;
162 + p[0] = value >> 8;
163 + p[1] = value;
164 +}
165 +
166 +static void PutBE24(void *out, unsigned int value)
167 +{
168 + unsigned char *p = out;
169 + p[0] = value >> 16;
170 + p[1] = value >> 8;
171 + p[2] = value;
172 +}
173 +
174 +/* ssl3_ForEachExtension calls a callback for each TLS extension in |extensions |
175 +** extensions: points to a block of extensions which includes the two prefix
176 +** length bytes
177 +** is_resuming: if true, certain extensions will be omitted
178 +** f: a function which is called with the data of each extension, which
179 +** includes the four type and length bytes at the beginning.
180 +*/
181 +static PRBool
182 +ssl3_ForEachExtension(const SECItem *extensions, PRBool is_resuming,
183 + void (*f) (const unsigned char *data, unsigned int length ,
184 + void *ctx),
185 + void *ctx) {
186 + unsigned int extensions_len, offset;
187 +
188 + if (extensions->len == 0)
189 + return PR_TRUE;
190 +
191 + if (extensions->len < 2)
192 + goto loser;
193 +
194 + extensions_len = GetBE16(extensions->data);
195 + offset = 2;
196 +
197 + if (extensions->len != 2 + extensions_len)
198 + goto loser;
199 +
200 + while (extensions_len) {
201 + unsigned int extension_num, extension_len;
202 +
203 + if (extensions->len - offset < 4)
204 + goto loser;
205 +
206 + extension_num = GetBE16(extensions->data + offset);
207 + extension_len = GetBE16(extensions->data + offset + 2);
208 +
209 + if (extensions->len - offset < 4 + extension_len)
210 + goto loser;
211 +
212 + /* When resuming, the server will omit some extensions from the
213 + * previous non-resume ServerHello. */
214 + if (!is_resuming ||
215 + (extension_num != ssl_server_name_xtn &&
216 + extension_num != ssl_session_ticket_xtn)) {
217 + f(extensions->data + offset, 4 + extension_len, ctx);
218 + }
219 +
220 + offset += 4 + extension_len;
221 + extensions_len -= 4 + extension_len;
222 + }
223 +
224 + return PR_TRUE;
225 +
226 +loser:
227 + PORT_SetError(SEC_ERROR_INPUT_LEN);
228 + return PR_FALSE;
229 +}
230 +
231 +static void
232 +ssl3_AccumlateLengths(const unsigned char *data, unsigned int length, void *ptr )
233 +{
234 + unsigned int *sum = (unsigned int *) ptr;
235 + *sum += length;
236 +}
237 +
238 +/* ssl3_PredictServerResponse predicts the contents of the server's
239 +** ServerHello...ServerHelloDone (inclusive) and progressively calls a callback
240 +** with the contents of those messages.
241 +** previous_server_hello: the contents of a previous ServerHello from the
242 +** server where the 'random' field has been replaced with our suggested
243 +** server random.
244 +** is_resuming: if false, Certificate and ServerHelloDone messages will be
245 +** predicted
246 +** hashUpdate: a callback which is called repeated with the contents of the
247 +** predicted messages.
248 +*/
249 +static PRBool
250 +ssl3_PredictServerResponse(
251 + sslSocket *ss, SECItem *previous_server_hello, PRBool is_resuming,
252 + void (*hashUpdate) (const unsigned char *data, unsigned int length,
253 + void *ctx),
254 + void *ctx) {
255 + unsigned int old_session_id_length, old_extensions_len;
256 + unsigned int extensions_len, server_hello_len;
257 + unsigned char session_id_len, header[4];
258 + SECItem extensions;
259 +
260 + /* Keep the structure of a ServerHello in mind when reading the following:
261 + *
262 + * struct ServerHello {
263 + * uint16_t version;
264 + * uint8_t random[32];
265 + * uint8_t session_id_len;
266 + * uint8_t session_id[session_id_len];
267 + * uint16_t cipher
268 + * uint8_t compression
269 + *
270 + * // Optional:
271 + * uint16_t extensions_len;
272 + * struct Extension {
273 + * uint16_t num;
274 + * uint16_t len;
275 + * uint8_t payload[len];
276 + * }
277 + */
278 +
279 + /* 38 bytes is the shortest possible ServerHello with a zero-length
280 + * session_id and no extensions. */
281 + if (previous_server_hello->len < 38) {
282 + PORT_SetError(SEC_ERROR_INPUT_LEN);
283 + return PR_FALSE;
284 + }
285 +
286 + /* First we need to figure out the length of the predicted ServerHello. Any
287 + * session id in |previous_server_hello| needs to be removed
288 + * (or replaced). */
289 + old_session_id_length = previous_server_hello->data[34];
290 +
291 + extensions.len = 0;
292 +
293 + if (previous_server_hello->len >= 35 + old_session_id_length + 3 + 2) {
294 + /* Extensions present */
295 + unsigned int offset = 35 + old_session_id_length + 3;
296 + extensions.data = previous_server_hello->data + offset;
297 + extensions.len = previous_server_hello->len - offset;
298 + }
299 +
300 + /* Sum the lengths of all the extensions that we wish to include */
301 + extensions_len = 0;
302 + if (!ssl3_ForEachExtension(&extensions, is_resuming, ssl3_AccumlateLengths,
303 + &extensions_len)) {
304 + return PR_FALSE;
305 + }
306 +
307 + old_extensions_len =
308 + (previous_server_hello->len - 35 - old_session_id_length - 3 - 2);
309 +
310 + session_id_len = 0;
311 + if (ss->sec.ci.sid)
312 + session_id_len = ss->sec.ci.sid->u.ssl3.sessionIDLength;
313 + server_hello_len = previous_server_hello->len +
314 + session_id_len - old_session_id_length +
315 + extensions_len - old_extensions_len;
316 +
317 + header[0] = server_hello;
318 + PutBE24(header + 1, server_hello_len);
319 + hashUpdate(header, 4, ctx);
320 +
321 + hashUpdate(previous_server_hello->data, 34, ctx);
322 + hashUpdate(&session_id_len, sizeof(session_id_len), ctx);
323 + if (session_id_len)
324 + hashUpdate(ss->sec.ci.sid->u.ssl3.sessionID, session_id_len, ctx);
325 + hashUpdate(previous_server_hello->data + 35 + old_session_id_length, 3,
326 + ctx);
327 +
328 + if (extensions.len) {
329 + PutBE16(header, extensions_len);
330 + hashUpdate(header, 2, ctx);
331 +
332 + if (!ssl3_ForEachExtension(&extensions, is_resuming, hashUpdate, ctx))
333 + return PR_FALSE;
334 + }
335 +
336 + if (!is_resuming) {
337 + unsigned int certificate_message_len = 3, i;
338 + for (i = 0; ss->ssl3.predictedCertChain[i]; i++) {
339 + certificate_message_len += 3;
340 + certificate_message_len +=
341 + ss->ssl3.predictedCertChain[i]->derCert.len;
342 + }
343 +
344 + header[0] = certificate;
345 + PutBE24(header + 1, certificate_message_len);
346 + hashUpdate(header, 4, ctx);
347 +
348 + PutBE24(header, certificate_message_len - 3);
349 + hashUpdate(header, 3, ctx);
350 +
351 + for (i = 0; ss->ssl3.predictedCertChain[i]; i++) {
352 + unsigned int len = ss->ssl3.predictedCertChain[i]->derCert.len;
353 + PutBE24(header, len);
354 + hashUpdate(header, 3, ctx);
355 + hashUpdate(ss->ssl3.predictedCertChain[i]->derCert.data, len, ctx);
356 + }
357 +
358 + header[0] = server_hello_done;
359 + header[1] = header[2] = header[3] = 0;
360 + hashUpdate(header, 4, ctx);
361 + }
362 +
363 + return PR_TRUE;
364 +}
365 +
366 +/* ssl3_SnapStartHash is called with the contents of the server's predicted
367 + * response and updates both the Finished hash and an FNV641a hash. */
368 +static void
369 +ssl3_SnapStartHash(const unsigned char *data, unsigned int len, void *ctx)
370 +{
371 + SECStatus rv;
372 + void **ptrs = (void **) ctx;
373 + sslSocket *ss = ptrs[0];
374 + PRUint64 *fnv = ptrs[1];
375 +
376 + FNV1A64_Update(fnv, data, len);
377 + rv = ssl3_UpdateHandshakeHashes(ss, (unsigned char *) data, len);
378 + if (rv != SECSuccess)
379 + PR_Assert("rv == SECSuccess", __FILE__, __LINE__);
380 +}
381 +
382 +static PRInt32
383 +ssl3_SendEmptySnapStartXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
384 +{
385 + SECStatus rv;
386 +
387 + if (maxBytes < 4)
388 + return 0;
389 +
390 + if (append) {
391 + rv = ssl3_AppendHandshakeNumber(ss, ssl_snap_start_xtn, 2);
392 + if (rv != SECSuccess)
393 + return -1;
394 + rv = ssl3_AppendHandshakeNumber(ss, 0 /* empty extension */, 2);
395 + if (rv != SECSuccess)
396 + return -1;
397 + if (!ss->sec.isServer) {
398 + TLSExtensionData *xtnData = &ss->xtnData;
399 + xtnData->advertised[xtnData->numAdvertised++] = ssl_snap_start_xtn;
400 + }
401 + }
402 + return 4;
403 +}
404 +
405 +static SECStatus
406 +ssl3_BufferEnsure(sslBuffer *buf, unsigned int extra_bytes)
407 +{
408 + if (buf->space < buf->len + extra_bytes)
409 + return sslBuffer_Grow(buf, buf->len + extra_bytes);
410 + return SECSuccess;
411 +}
412 +
413 +/* ssl3_AppendSnapStartRecordHeader appends a 5 byte TLS record header to the
414 + * sendBuf of the given sslSocket. */
415 +static SECStatus
416 +ssl3_AppendSnapStartRecordHeader(sslSocket *ss, SSL3ContentType type,
417 + unsigned int len)
418 +{
419 + SECStatus rv;
420 +
421 + rv = ssl3_BufferEnsure(&ss->sec.ci.sendBuf, 5);
422 + if (rv != SECSuccess)
423 + return rv;
424 + ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len + 0] = type;
425 + PutBE16(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len + 1], ss->version);
426 + PutBE16(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len + 3], len);
427 + ss->sec.ci.sendBuf.len += 5;
428 + return SECSuccess;
429 +}
430 +
431 +/* ssl3_AppendSnapStartHandshakeRecord appends a (possibly encrypted) record to
432 +** the sendBuf of the given sslSocket.
433 +** f: a function which will append the bytes of the record (not including the
434 +** 5 byte header) to the sendBuf.
435 +*/
436 +static SECStatus
437 +ssl3_AppendSnapStartHandshakeRecord(sslSocket *ss, SECStatus (*f) (sslSocket*),
438 + PRBool encrypt)
439 +{
440 + SECStatus rv;
441 + unsigned int record_offset, record_len;
442 +
443 + /* ssl3_CompressMACEncryptRecord will deal with the record header if we are
444 + * encrypting. */
445 + if (!encrypt) {
446 + /* The zero length argument here is a dummy value. We write the real
447 + * length once we know it, below. */
448 + rv = ssl3_AppendSnapStartRecordHeader(ss, content_handshake, 0);
449 + if (rv != SECSuccess)
450 + return rv;
451 + }
452 +
453 + record_offset = ss->sec.ci.sendBuf.len;
454 + rv = f(ss);
455 + if (rv != SECSuccess)
456 + return rv;
457 + record_len = ss->sec.ci.sendBuf.len - record_offset;
458 + if (!encrypt) {
459 + PutBE16(&ss->sec.ci.sendBuf.buf[record_offset - 2], record_len);
460 + } else {
461 + /* ssl3_CompressMACEncryptRecord writes to |ss->sec.writeBuf|
462 + * so we copy it back to |ss->sec.ci.sendBuf| */
463 + /* TODO(agl): the buffer copy here is a bodge. See TODO at the top of
464 + * the file. */
465 + rv = ssl3_CompressMACEncryptRecord(
466 + ss, content_handshake,
467 + &ss->sec.ci.sendBuf.buf[record_offset], record_len);
468 + if (rv != SECSuccess)
469 + return rv;
470 + ss->sec.ci.sendBuf.len -= record_len;
471 + ssl3_BufferEnsure(&ss->sec.ci.sendBuf, ss->sec.writeBuf.len);
472 + memcpy(&ss->sec.ci.sendBuf.buf[record_offset], ss->sec.writeBuf.buf,
473 + ss->sec.writeBuf.len);
474 + ss->sec.ci.sendBuf.len += ss->sec.writeBuf.len;
475 + ss->sec.writeBuf.len = 0;
476 + }
477 +
478 + return SECSuccess;
479 +}
480 +
481 +/* ssl3_AppendSnapStartApplicationData appends an encrypted Application Data
482 +** record the sendBuf of the given sslSocket.
483 +*/
484 +static SECStatus ssl3_AppendSnapStartApplicationData(
485 + sslSocket *ss, const SSL3Opaque *data, unsigned int len)
486 +{
487 + SECStatus rv;
488 +
489 + /* TODO(agl): the buffer copy here is a bodge. See TODO at the top of the
490 + * file. */
491 + rv = ssl3_CompressMACEncryptRecord(ss, content_application_data, data, len) ;
492 + if (rv != SECSuccess)
493 + return rv;
494 + rv = ssl3_BufferEnsure(&ss->sec.ci.sendBuf, ss->sec.writeBuf.len);
495 + if (rv != SECSuccess)
496 + return rv;
497 + memcpy(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len],
498 + ss->sec.writeBuf.buf, ss->sec.writeBuf.len);
499 + ss->sec.ci.sendBuf.len += ss->sec.writeBuf.len;
500 + ss->sec.writeBuf.len = 0;
501 +
502 + return SECSuccess;
503 +}
504 +
505 +static SECStatus ssl3_SendSnapStartFinished(sslSocket *ss)
506 +{
507 + /* We use ssl_SEND_FLAG_NO_FLUSH here because this finished message is
508 + * going to end up in the middle of the Snap Start extension. So
509 + * transmitting |sendBuf| at this point would result in an incomplete
510 + * ClientHello. */
511 + return ssl3_SendFinished(ss, ssl_SEND_FLAG_NO_FLUSH);
512 +}
513 +
514 +/* ssl3_FindOrbit is called for each extension in a ServerHello message. It
515 +** tests for a Snap Start extension and records the server's orbit when found.
516 +** data: the extension data (including the four type and length bytes)
517 +** length: the length, in bytes, of |data|
518 +** ptr: a pointer to a uint8_t[9]. The orbit, if found, is copied into the
519 +** first 8 bytes and then the ninth byte is set to one.
520 +*/
521 +static void
522 +ssl3_FindOrbit(const unsigned char *data, unsigned int length, void *ptr)
523 +{
524 + unsigned char *orbit = (unsigned char *) ptr;
525 +
526 + unsigned int extension_num = GetBE16(data);
527 + if (extension_num == ssl_snap_start_xtn &&
528 + length == 4 + 8 /* orbit */ + 2 /* snap start cipher suite */) {
529 + memcpy(orbit, data + 4, 8);
530 + /* A last byte of 1 indicates that the previous eight are valid. */
531 + orbit[8] = 1;
532 + }
533 +}
534 +
535 +/* ssl3_CanSnapStart returns true if we are able to perform Snap Start on
536 +** the given socket.
537 +** extensions: on successful return, this is filled in with the contents of
538 +** the server's predicted extensions. This points within
539 +** |ss->ssl3.serverHelloPredictionData|.
540 +** resuming: PR_TRUE iff we wish to attempt a Snap Start resume
541 +** out_orbit: if this function returns PR_TRUE, then |out_orbit| is filled
542 +** with the server's predicted orbit value.
543 +** The |hs.cipher_suite|, |hs.cipher_def| and |hs.compression| fields of |ss|
544 +** are set to match the predicted ServerHello on successful exit (and may still
545 +** be modified on failure).
546 +*/
547 +static PRBool
548 +ssl3_CanSnapStart(sslSocket *ss, SECItem *extensions, PRBool resuming,
549 + unsigned char out_orbit[8]) {
550 + const unsigned char *server_hello;
551 + unsigned int server_hello_len, session_id_len, cipher_suite_offset;
552 + unsigned int extensions_offset, cipher_suite, compression_method;
553 + unsigned char orbit[9];
554 + SECStatus rv;
555 + SSL3ProtocolVersion version;
556 +
557 + /* If we don't have the information needed then we can't perform a Snap
558 + * Start. */
559 + if (!ss->ssl3.predictedCertChain || !ss->ssl3.serverHelloPredictionData.dat a)
560 + return PR_FALSE;
561 +
562 + /* When the sizes of the fields in the ClientHello are calculated, they'll
563 + * take the length of the Snap Start extension to be zero, so currently
564 + * it's as if this extension didn't exist, which is the state that we
565 + * need. */
566 +
567 + server_hello = ss->ssl3.serverHelloPredictionData.data;
568 + server_hello_len = ss->ssl3.serverHelloPredictionData.len;
569 +
570 + if (server_hello_len < 2 + 32 + 1)
571 + return PR_FALSE;
572 + session_id_len = server_hello[2 + 32];
573 + cipher_suite_offset = 2 + 32 + 1 + session_id_len;
574 + if (server_hello_len < cipher_suite_offset + 3)
575 + return PR_FALSE;
576 + extensions_offset = cipher_suite_offset + 3;
577 +
578 + version = (SSL3ProtocolVersion) GetBE16(server_hello);
579 + if (MSB(version) < MSB(SSL_LIBRARY_VERSION_3_0))
580 + return PR_FALSE;
581 + rv = ssl3_NegotiateVersion(ss, version);
582 + if (rv != SECSuccess)
583 + return PR_FALSE;
584 +
585 + cipher_suite = GetBE16(&server_hello[cipher_suite_offset]);
586 + ss->ssl3.hs.cipher_suite = (ssl3CipherSuite)cipher_suite;
587 + ss->ssl3.hs.suite_def = ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite);
588 + if (!ss->ssl3.hs.suite_def)
589 + return PR_FALSE;
590 + compression_method = server_hello[cipher_suite_offset + 2];
591 + if (compression_method != ssl_compression_null) {
592 + /* TODO(agl): support compression. */
593 + return PR_FALSE;
594 + }
595 + ss->ssl3.hs.compression = ssl_compression_null;
596 +
597 + extensions->data = (unsigned char *) server_hello + extensions_offset;
598 + extensions->len = server_hello_len - extensions_offset;
599 +
600 + /* The last byte is used to indictate that the previous eight are valid. */
601 + orbit[8] = 0;
602 + if (!ssl3_ForEachExtension(extensions, resuming, ssl3_FindOrbit, orbit))
603 + return PR_FALSE;
604 +
605 + if (!orbit[8])
606 + return PR_FALSE;
607 +
608 + memcpy(out_orbit, orbit, 8);
609 +
610 + return PR_TRUE;
611 +}
612 +
613 +/* ssl3_UpdateClientHelloLengths rewrites the handshake header length and
614 +** extensions length in the ClientHello to reflect the addition of the Snap
615 +** Start extension.
616 +** snap_start_extension_len_offset: the number of bytes of the ClientHello to
617 +** skip in order to find the embedded length of the Snap Start extension.
618 +*/
619 +static void
620 +ssl3_UpdateClientHelloLengths(sslSocket *ss,
621 + unsigned int snap_start_extension_len_offset,
622 + sslSessionID *sid) {
623 + unsigned int extension_length, old_length, new_length, new_session_id_len;
624 + unsigned int offset, ciphers_length, compressions_len;
625 +
626 + extension_length =
627 + ss->sec.ci.sendBuf.len - snap_start_extension_len_offset - 2;
628 + PutBE16(&ss->sec.ci.sendBuf.buf[snap_start_extension_len_offset],
629 + extension_length);
630 +
631 + /* The length in the handshake header is short by extension_length + 4
632 + * bytes. */
633 + old_length = GetBE24(&ss->sec.ci.sendBuf.buf[1]);
634 + new_length = old_length + extension_length + 4;
635 + PutBE24(&ss->sec.ci.sendBuf.buf[1], new_length);
636 +
637 + /* The length of the extensions block is similarly wrong. */
638 + new_session_id_len = 0;
639 + if (sid)
640 + new_session_id_len = sid->u.ssl3.sessionIDLength;
641 + offset = 4 + 2 + 32 + 1 + new_session_id_len;
642 + ciphers_length = GetBE16(&ss->sec.ci.sendBuf.buf[offset]);
643 + offset += 2 + ciphers_length;
644 + compressions_len = ss->sec.ci.sendBuf.buf[offset];
645 + offset += 1 + compressions_len;
646 + old_length = GetBE16(&ss->sec.ci.sendBuf.buf[offset]);
647 + new_length = old_length + extension_length + 4;
648 + PutBE16(&ss->sec.ci.sendBuf.buf[offset], new_length);
649 +}
650 +
651 +/* ssl3_FindServerNPNExtension is a callback function for ssl3_ForEachExtension .
652 + * It looks for a Next Protocol Negotiation and saves the payload of the
653 + * extension in the given SECItem */
654 +static void
655 +ssl3_FindServerNPNExtension(const unsigned char* data, unsigned int length,
656 + void *ctx)
657 +{
658 + SECItem *server_npn_extension = (SECItem*) ctx;
659 +
660 + unsigned int extension_num = GetBE16(data);
661 + if (extension_num == ssl_next_proto_neg_xtn && length >= 4) {
662 + server_npn_extension->data = (unsigned char*)data + 4;
663 + server_npn_extension->len = length - 4;
664 + }
665 +}
666 +
667 +/* ssl3_MaybeWriteNextProtocol deals with the interaction of Next Protocol
668 + * Negotiation and Snap Start. It's called just before we serialise the embedde d
669 + * Finished message in the extension. At this point, if NPN is enabled, we have
670 + * to include a NextProtocol message. */
671 +static SECStatus
672 +ssl3_MaybeWriteNextProtocol(sslSocket *ss, SECItem *server_hello_extensions)
673 +{
674 + PRUint16 i16;
675 + SECItem server_npn_extension;
676 +
677 + for (i16 = 0; i16 < ss->xtnData.numAdvertised; i16++) {
678 + if (ss->xtnData.advertised[i16] == ssl_next_proto_neg_xtn)
679 + break;
680 + }
681 +
682 + if (i16 == ss->xtnData.numAdvertised) {
683 + /* We didn't send an NPN extension, so no need to do anything here. */
684 + return SECSuccess;
685 + }
686 +
687 + memset(&server_npn_extension, 0, sizeof(server_npn_extension));
688 +
689 + ssl3_ForEachExtension(
690 + server_hello_extensions, PR_FALSE /* is_resuming: value doesn't matter
691 + in this case */, ssl3_FindServerNPNExtension, &server_npn_extension);
692 +
693 + if (server_npn_extension.data == NULL) {
694 + /* We predicted that the server doesn't support NPN, so nothing to do
695 + * here. */
696 + return SECSuccess;
697 + }
698 +
699 + ssl3_ClientHandleNextProtoNegoXtn(ss, ssl_next_proto_neg_xtn,
700 + &server_npn_extension);
701 +
702 + if (ss->ssl3.nextProtoState == SSL_NEXT_PROTO_NO_SUPPORT) {
703 + /* The server's predicted NPN extension was malformed. We're didn't pic k
704 + * a protocol so we won't send a NextProtocol message. However, this is
705 + * probably fatal to the connection. */
706 + return SECSuccess;
707 + }
708 +
709 + return ssl3_AppendSnapStartHandshakeRecord(ss, ssl3_SendNextProto,
710 + PR_TRUE /* encrypt */);
711 +}
712 +
713 +/* ssl3_SendSnapStartXtn appends a Snap Start extension. It assumes that the
714 + * inchoate ClientHello is in |ss->sec.ci.sendBuf|. */
715 +PRInt32
716 +ssl3_SendSnapStartXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
717 +{
718 + unsigned char orbit[8];
719 + PRBool resuming = PR_FALSE;
720 + unsigned char suggested_server_random[32];
721 + SECStatus rv;
722 + PRUint64 fnv;
723 + /* The context for |ssl3_SnapStartHash|. The first pointer points to |ss|
724 + * and the second to the running FNV1A64 hash of the predicted server
725 + * response. */
726 + void *ctx[2];
727 + unsigned int snap_start_extension_len_offset, original_sendbuf_len;
728 + ssl3CipherSpec *temp;
729 + sslSessionID *sid;
730 + SECItem server_extensions;
731 +
732 + if (!ss->opt.enableSnapStart)
733 + return 0;
734 +
735 + original_sendbuf_len = ss->sec.ci.sendBuf.len;
736 +
737 + /* This function is called twice for each ClientHello emitted. The first
738 + * time around is to calculate the sizes of the extension (|append| is
739 + * false). The second time around is to actually write out the bytes
740 + * (|append| is true).
741 + *
742 + * We always return 0 bytes in each case because we want to be able to hash
743 + * the inchoate ClientHello as if this extension was missing: that's why
744 + * it's important that this always be the last extension serialised. */
745 + sid = ss->sec.ci.sid;
746 +
747 + if (!ss->opt.enableSessionTickets || ss->sec.isServer)
748 + return 0;
749 +
750 + /* If we are sending a SessionTicket then the first time around
751 + * ticketTimestampVerified will be true but it's reset after serialising
752 + * the session ticket extension, so we have
753 + * |clientSentNonEmptySessionTicket|. */
754 + if (ss->xtnData.clientSentNonEmptySessionTicket) {
755 + resuming = PR_TRUE;
756 + } else if (sid->u.ssl3.sessionTicket.ticket.data &&
757 + ss->xtnData.ticketTimestampVerified) {
758 + resuming = PR_TRUE;
759 + }
760 +
761 + if (!ssl3_CanSnapStart(ss, &server_extensions, resuming, orbit))
762 + return ssl3_SendEmptySnapStartXtn(ss, append, maxBytes);
763 +
764 + /* At this point we are happy that we are going to send a non-empty Snap
765 + * Start extension. If we are still calculating length then we lie and
766 + * return 0 so that everything is set up as if the extension didn't exist
767 + * when this function is called again later. */
768 +
769 + if (!append)
770 + return 0;
771 +
772 + /* |ss->sec.ci.sendBuf.buf| contains the inchoate ClientHello. This copies
773 + * the ClientHello's gmt_unix_time into the suggested server random. */
774 + memcpy(suggested_server_random, ss->sec.ci.sendBuf.buf + 6, 4);
775 + memcpy(suggested_server_random + 4, orbit, 8);
776 + rv = PK11_GenerateRandom(suggested_server_random + 12, 20);
777 + if (rv != SECSuccess)
778 + goto loser;
779 + memcpy(ss->ssl3.serverHelloPredictionData.data + 2, suggested_server_random ,
780 + 32);
781 +
782 + memcpy(&ss->ssl3.hs.server_random, suggested_server_random, 32);
783 +
784 + PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
785 + rv = ssl3_SetupPendingCipherSpec(ss);
786 + if (rv != SECSuccess)
787 + goto loser;
788 + ss->ssl3.hs.isResuming = resuming;
789 +
790 + FNV1A64_Init(&fnv);
791 + ctx[0] = ss;
792 + ctx[1] = &fnv;
793 +
794 + if (!ssl3_PredictServerResponse(ss, &ss->ssl3.serverHelloPredictionData,
795 + resuming, ssl3_SnapStartHash, ctx)) {
796 + /* It's not a fatal error if the predicted ServerHello was invalid. */
797 + return 0;
798 + }
799 + FNV1A64_Final(&fnv);
800 +
801 + /* Now we grow the send buffer to accomodate the extension type and length,
802 + * orbit, suggested random and predicted server response hash without
803 + * calling ssl3_AppendHandshake (which would also update the Finished
804 + * hash). */
805 + if (ssl3_BufferEnsure(&ss->sec.ci.sendBuf, 4 + 8 + 20 + 8) != SECSuccess)
806 + goto loser;
807 +
808 + PutBE16(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len],
809 + ssl_snap_start_xtn);
810 + ss->sec.ci.sendBuf.len += 2;
811 + /* Skip over the length for now. */
812 + snap_start_extension_len_offset = ss->sec.ci.sendBuf.len;
813 + ss->sec.ci.sendBuf.len += 2;
814 + memcpy(ss->sec.ci.sendBuf.buf + ss->sec.ci.sendBuf.len, orbit, 8);
815 + ss->sec.ci.sendBuf.len += 8;
816 + memcpy(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len],
817 + suggested_server_random + 12, 20);
818 + ss->sec.ci.sendBuf.len += 20;
819 + memcpy(ss->sec.ci.sendBuf.buf + ss->sec.ci.sendBuf.len, &fnv, 8);
820 + ss->sec.ci.sendBuf.len += 8;
821 +
822 + if (!resuming) {
823 + /* Write ClientKeyExchange */
824 + ss->sec.peerCert =
825 + CERT_DupCertificate(ss->ssl3.predictedCertChain[0]);
826 + rv = ssl3_AppendSnapStartHandshakeRecord(
827 + ss, ssl3_SendClientKeyExchange, PR_FALSE /* do not encrypt */);
828 + if (rv != SECSuccess)
829 + goto loser;
830 + } else {
831 + SSL3Finished hashes;
832 + TLSFinished tlsFinished;
833 + unsigned char hdr[4];
834 +
835 + rv = ssl3_SetupMasterSecretFromSessionID(ss);
836 + if (rv == SECFailure)
837 + goto loser;
838 +
839 + if (sid->peerCert != NULL) {
840 + ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
841 + ssl3_CopyPeerCertsFromSID(ss, sid);
842 + }
843 +
844 + rv = ssl3_InitPendingCipherSpec(ss, NULL /* re-use master secret */);
845 + if (rv != SECSuccess)
846 + goto loser;
847 +
848 + /* Need to add the server's predicted Finished message to our handshake
849 + * hash in order to be able to produce our own Finished message. */
850 + rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.pwSpec, &hashes,
851 + 0 /* only for SSL3 */);
852 + if (rv != SECSuccess)
853 + goto loser;
854 +
855 + rv = ssl3_ComputeTLSFinished(ss->ssl3.pwSpec, PR_TRUE /* isServer */,
856 + &hashes, &tlsFinished);
857 + if (rv != SECSuccess)
858 + goto loser;
859 +
860 + hdr[0] = (unsigned char) finished;
861 + hdr[1] = hdr[2] = 0;
862 + hdr[3] = sizeof(tlsFinished.verify_data);
863 + ssl3_UpdateHandshakeHashes(ss, hdr, sizeof(hdr));
864 + ssl3_UpdateHandshakeHashes(ss, tlsFinished.verify_data,
865 + sizeof(tlsFinished.verify_data));
866 +
867 + /* Store the Finished message so that we can verify it later */
868 + memcpy(&ss->ssl3.hs.finishedMsgs.tFinished[1], tlsFinished.verify_data,
869 + sizeof(tlsFinished.verify_data));
870 + }
871 +
872 + /* Write ChangeCipherSpec */
873 + rv = ssl3_AppendSnapStartRecordHeader(ss, content_change_cipher_spec, 1);
874 + if (rv != SECSuccess)
875 + goto loser;
876 + rv = ssl3_BufferEnsure(&ss->sec.ci.sendBuf, 1);
877 + if (rv != SECSuccess)
878 + goto loser;
879 + ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len] = change_cipher_spec_choice;
880 + ss->sec.ci.sendBuf.len++;
881 +
882 + /* We swap |cwSpec| and |pwSpec| temporarily in order to encrypt some
883 + * records before switching them back so that the whole ClientHello doesn't
884 + * get encrypted. */
885 + ssl_GetSpecWriteLock(ss);
886 + temp = ss->ssl3.cwSpec;
887 + ss->ssl3.cwSpec = ss->ssl3.pwSpec;
888 + ss->ssl3.pwSpec = temp;
889 + ss->ssl3.cwSpec->write_seq_num.high = 0;
890 + ss->ssl3.cwSpec->write_seq_num.low = 0;
891 + ssl_ReleaseSpecWriteLock(ss);
892 +
893 + rv = ssl3_MaybeWriteNextProtocol(ss, &server_extensions);
894 + if (rv != SECSuccess)
895 + goto loser;
896 +
897 + /* Write Finished */
898 + rv = ssl3_AppendSnapStartHandshakeRecord(ss, ssl3_SendSnapStartFinished,
899 + PR_TRUE /* encrypt */);
900 + if (rv != SECSuccess)
901 + goto loser;
902 +
903 + /* Write application data */
904 + if (ss->ssl3.snapStartApplicationData.data) {
905 + rv = ssl3_AppendSnapStartApplicationData(
906 + ss, ss->ssl3.snapStartApplicationData.data,
907 + ss->ssl3.snapStartApplicationData.len);
908 + if (rv != SECSuccess)
909 + goto loser;
910 + }
911 +
912 + /* Revert the write cipher spec because the ClientHello will get encrypted
913 + * with it otherwise. */
914 + ssl_GetSpecWriteLock(ss);
915 + temp = ss->ssl3.cwSpec;
916 + ss->ssl3.cwSpec = ss->ssl3.pwSpec;
917 + ss->ssl3.pwSpec = temp;
918 + ssl_ReleaseSpecWriteLock(ss);
919 +
920 + /* Update the lengths in the ClientHello to reflect this extension. */
921 + ssl3_UpdateClientHelloLengths(ss, snap_start_extension_len_offset, sid);
922 +
923 + /* Keep a copy of the ClientHello around so that we can hash it in the case
924 + * the the Snap Start handshake is rejected. */
925 +
926 + if (SECITEM_AllocItem(NULL, &ss->ssl3.hs.origClientHello,
927 + ss->sec.ci.sendBuf.len) == NULL) {
928 + goto loser;
929 + }
930 + memcpy(ss->ssl3.hs.origClientHello.data, ss->sec.ci.sendBuf.buf,
931 + ss->sec.ci.sendBuf.len);
932 + ss->ssl3.hs.origClientHello.len = ss->sec.ci.sendBuf.len;
933 +
934 + ss->xtnData.advertised[ss->xtnData.numAdvertised++] = ssl_snap_start_xtn;
935 +
936 + if (resuming) {
937 + ss->ssl3.hs.snapStartType = snap_start_resume;
938 + } else {
939 + ss->ssl3.hs.snapStartType = snap_start_full;
940 + }
941 +
942 + return 0;
943 +
944 +loser:
945 + /* In the case of an error we revert the length of the sendBuf to remove
946 + * any partial data that we may have appended. */
947 + ss->sec.ci.sendBuf.len = original_sendbuf_len;
948 + return -1;
949 +}
950 +
951 +SECStatus ssl3_ClientHandleSnapStartXtn(sslSocket *ss, PRUint16 ex_type,
952 + SECItem *data) {
953 + /* The work of saving the ServerHello is done in ssl3_HandleServerHello,
954 + * where its contents are available. Here we renognise that the saved
955 + * ServerHello message contains a Snap Start extension and mark it as
956 + * valid. */
957 + ss->ssl3.serverHelloPredictionDataValid = PR_TRUE;
958 + return SECSuccess;
959 +}
960 +
961 +SECStatus
962 +SSL_SetPredictedPeerCertificates(PRFileDesc *fd, CERTCertificate **certs,
963 + unsigned int numCerts)
964 +{
965 + sslSocket *ss;
966 + unsigned int i;
967 +
968 + ss = ssl_FindSocket(fd);
969 + if (!ss) {
970 + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetPredictedPeerCertificates",
971 + SSL_GETPID(), fd));
972 + return SECFailure;
973 + }
974 +
975 + ss->ssl3.predictedCertChain =
976 + PORT_NewArray(CERTCertificate*, numCerts + 1);
977 + if (!ss->ssl3.predictedCertChain)
978 + return SECFailure; /* error code was set */
979 + for (i = 0; i < numCerts; i++)
980 + ss->ssl3.predictedCertChain[i] = CERT_DupCertificate(certs[i]);
981 + ss->ssl3.predictedCertChain[numCerts] = NULL;
982 +
983 + return SECSuccess;
984 +}
985 +
986 +void
987 +ssl3_CleanupPredictedPeerCertificates(sslSocket *ss) {
988 + unsigned int i;
989 +
990 + if (!ss->ssl3.predictedCertChain)
991 + return;
992 +
993 + for (i = 0; ss->ssl3.predictedCertChain[i]; i++) {
994 + CERT_DestroyCertificate(ss->ssl3.predictedCertChain[i]);
995 + }
996 +
997 + PORT_Free(ss->ssl3.predictedCertChain);
998 + ss->ssl3.predictedCertChain = NULL;
999 +}
1000 +
1001 +SECStatus
1002 +SSL_GetPredictedServerHelloData(PRFileDesc *fd, const unsigned char **data,
1003 + unsigned int *data_len)
1004 +{
1005 + sslSocket *ss;
1006 +
1007 + ss = ssl_FindSocket(fd);
1008 + if (!ss) {
1009 + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetPredictedServerHelloData",
1010 + SSL_GETPID(), fd));
1011 + *data = NULL;
1012 + *data_len = 0;
1013 + return SECFailure;
1014 + }
1015 +
1016 + if (!ss->ssl3.serverHelloPredictionDataValid) {
1017 + *data = NULL;
1018 + *data_len = 0;
1019 + } else {
1020 + *data = ss->ssl3.serverHelloPredictionData.data;
1021 + *data_len = ss->ssl3.serverHelloPredictionData.len;
1022 + }
1023 + return SECSuccess;
1024 +}
1025 +
1026 +SECStatus
1027 +SSL_SetPredictedServerHelloData(PRFileDesc *fd, const unsigned char *data,
1028 + unsigned int data_len)
1029 +{
1030 + sslSocket *ss;
1031 +
1032 + ss = ssl_FindSocket(fd);
1033 + if (!ss) {
1034 + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetPredictedServerHelloData",
1035 + SSL_GETPID(), fd));
1036 + return SECFailure;
1037 + }
1038 +
1039 + if (ss->ssl3.serverHelloPredictionData.data)
1040 + SECITEM_FreeItem(&ss->ssl3.serverHelloPredictionData, PR_FALSE);
1041 + if (!SECITEM_AllocItem(NULL, &ss->ssl3.serverHelloPredictionData, data_len) )
1042 + return SECFailure;
1043 + memcpy(ss->ssl3.serverHelloPredictionData.data, data, data_len);
1044 + return SECSuccess;
1045 +}
1046 +
1047 +SECStatus
1048 +SSL_SetSnapStartApplicationData(PRFileDesc *fd, const unsigned char *data,
1049 + unsigned int data_len)
1050 +{
1051 + sslSocket *ss;
1052 +
1053 + ss = ssl_FindSocket(fd);
1054 + if (!ss) {
1055 + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetSnapStartApplicationData",
1056 + SSL_GETPID(), fd));
1057 + return SECFailure;
1058 + }
1059 +
1060 + if (ss->ssl3.snapStartApplicationData.data)
1061 + SECITEM_FreeItem(&ss->ssl3.snapStartApplicationData, PR_FALSE);
1062 + if (!SECITEM_AllocItem(NULL, &ss->ssl3.snapStartApplicationData, data_len))
1063 + return SECFailure;
1064 + memcpy(ss->ssl3.snapStartApplicationData.data, data, data_len);
1065 + return SECSuccess;
1066 +}
1067 +
1068 +SECStatus
1069 +SSL_GetSnapStartResult(PRFileDesc *fd, SSLSnapStartResult *result)
1070 +{
1071 + sslSocket *ss;
1072 +
1073 + ss = ssl_FindSocket(fd);
1074 + if (!ss) {
1075 + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetSnapStartResult",
1076 + SSL_GETPID(), fd));
1077 + return SECFailure;
1078 + }
1079 +
1080 + switch (ss->ssl3.hs.snapStartType) {
1081 + case snap_start_full:
1082 + *result = SSL_SNAP_START_FULL;
1083 + break;
1084 + case snap_start_recovery:
1085 + *result = SSL_SNAP_START_RECOVERY;
1086 + break;
1087 + case snap_start_resume:
1088 + *result = SSL_SNAP_START_RESUME;
1089 + break;
1090 + case snap_start_resume_recovery:
1091 + *result = SSL_SNAP_START_RESUME_RECOVERY;
1092 + break;
1093 + default:
1094 + PORT_Assert(ss->ssl3.hs.snapStartType == snap_start_none);
1095 + *result = SSL_SNAP_START_NONE;
1096 + break;
1097 + }
1098 +
1099 + return SECSuccess;
1100 +}
1101 +
1102 +/* Called form ssl3_HandleServerHello in the case that we sent a Snap Start
1103 +** ClientHello but received a ServerHello in reply.
1104 +*/
1105 +SECStatus
1106 +ssl3_ResetForSnapStartRecovery(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
1107 +{
1108 + SECStatus rv;
1109 + PRUint8 hdr[4];
1110 +
1111 + ss->ssl3.hs.ws = wait_server_hello;
1112 +
1113 + /* Need to reset the Finished hashes to include the full ClientHello
1114 + * message. */
1115 +
1116 + rv = ssl3_RestartHandshakeHashes(ss);
1117 + if (rv != SECSuccess)
1118 + return rv;
1119 + rv = ssl3_UpdateHandshakeHashes(ss, ss->ssl3.hs.origClientHello.data,
1120 + ss->ssl3.hs.origClientHello.len);
1121 + SECITEM_FreeItem(&ss->ssl3.hs.origClientHello, PR_FALSE);
1122 + if (rv != SECSuccess)
1123 + return rv;
1124 +
1125 + hdr[0] = (PRUint8)server_hello;
1126 + hdr[1] = (PRUint8)(length >> 16);
1127 + hdr[2] = (PRUint8)(length >> 8);
1128 + hdr[3] = (PRUint8)(length );
1129 +
1130 + rv = ssl3_UpdateHandshakeHashes(ss, hdr, sizeof(hdr));
1131 + if (rv != SECSuccess)
1132 + return rv;
1133 + rv = ssl3_UpdateHandshakeHashes(ss, b, length);
1134 + if (rv != SECSuccess)
1135 + return rv;
1136 +
1137 + if (ss->ssl3.hs.snapStartType == snap_start_full) {
1138 + ss->ssl3.hs.snapStartType = snap_start_recovery;
1139 + } else {
1140 + ss->ssl3.hs.snapStartType = snap_start_resume_recovery;
1141 + }
1142 +
1143 + ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_TRUE/*freeSrvName*/);
1144 +
1145 + return SECSuccess;
1146 +}
1147 diff --git a/mozilla/security/nss/lib/ssl/ssl.def b/mozilla/security/nss/lib/ssl /ssl.def
1148 index a1f4b51..effc35d 100644
1149 --- a/mozilla/security/nss/lib/ssl/ssl.def
1150 +++ b/mozilla/security/nss/lib/ssl/ssl.def
1151 @@ -159,3 +159,13 @@ SSL_SetNextProtoNego;
1152 ;+ local:
1153 ;+*;
1154 ;+};
1155 +;+NSS_3.13 { # NSS 3.13 release
1156 +;+ global:
1157 +SSL_GetPredictedServerHelloData;
1158 +SSL_GetSnapStartResult;
1159 +SSL_SetPredictedPeerCertificates;
1160 +SSL_SetPredictedServerHelloData;
1161 +SSL_SetSnapStartApplicationData;
1162 +;+ local:
1163 +;+*;
1164 +;+};
1165 diff --git a/mozilla/security/nss/lib/ssl/ssl.h b/mozilla/security/nss/lib/ssl/s sl.h
1166 index d87ae56..8217d2e 100644
1167 --- a/mozilla/security/nss/lib/ssl/ssl.h
1168 +++ b/mozilla/security/nss/lib/ssl/ssl.h
1169 @@ -139,6 +139,15 @@ SSL_IMPORT PRFileDesc *SSL_ImportFD(PRFileDesc *model, PRFi leDesc *fd);
1170 /* occur on RSA or DH ciphersuites where the cipher's key length is >= 80 */
1171 /* bits. The advantage of False Start is that it saves a round trip for */
1172 /* client-speaks-first protocols when performing a full handshake. */
1173 +#define SSL_ENABLE_SNAP_START 23 /* Enable SSL snap start (off by */
1174 + /* default, applies only to */
1175 + /* clients). Snap start is a way */
1176 +/* of performing TLS handshakes with no round trips. The client's entire */
1177 +/* handshake is included in the first handshake message, along with */
1178 +/* optional application data. In order to do this, information from a */
1179 +/* previous connection to the same server is required. See */
1180 +/* SSL_GetPredictedServerHelloData, SSL_SetPredictedPeerCertificates and */
1181 +/* SSL_SetSnapStartApplicationData. */
1182
1183 #ifdef SSL_DEPRECATED_FUNCTION
1184 /* Old deprecated function names */
1185 @@ -376,6 +385,49 @@ SSL_IMPORT SECStatus SSL_BadCertHook(PRFileDesc *fd, SSLBad CertHandler f,
1186 void *arg);
1187
1188 /*
1189 +** Set the predicted chain of certificates for the peer. This is used for the
1190 +** TLS Snap Start extension. Note that the SSL_ENABLE_SNAP_START option must
1191 +** be set for this to occur.
1192 +**
1193 +** This function takes a reference to each of the given certificates.
1194 +*/
1195 +SSL_IMPORT SECStatus SSL_SetPredictedPeerCertificates(
1196 + PRFileDesc *fd, CERTCertificate **certs,
1197 + unsigned int numCerts);
1198 +
1199 +/*
1200 +** Get the data needed to predict the server's hello message in the future. On
1201 +** return, |*data| will either be NULL (in which case no data is available and
1202 +** |*data_len| will be zero) or it will point to a buffer within the internal
1203 +** data of |fd| and |*data_len| will contain the number of bytes available. If
1204 +** non-NULL, |*data| will persist at least until the next handshake on |fd|.
1205 +*/
1206 +SSL_IMPORT SECStatus SSL_GetPredictedServerHelloData(
1207 + PRFileDesc *fd, const unsigned char **data,
1208 + unsigned int *data_len);
1209 +
1210 +/*
1211 +** Set the predicted server hello data. This is used for the TLS Snap Start
1212 +** extension. Note that the SSL_ENABLE_SNAP_START option must be set for this
1213 +** to occur.
1214 +*/
1215 +SSL_IMPORT SECStatus SSL_SetPredictedServerHelloData(
1216 + PRFileDesc *fd, const unsigned char *data, unsigned int data_len);
1217 +
1218 +/* Set the application data which will be transmitted in a Snap Start
1219 +** handshake. If the Snap Start handshake fails, this data will be
1220 +* retransmitted automatically. */
1221 +SSL_IMPORT SECStatus SSL_SetSnapStartApplicationData(
1222 + PRFileDesc *fd, const unsigned char *data, unsigned int data_len);
1223 +
1224 +/* Get the result of a Snap Start handshake. It's valid to call then even if
1225 +** SSL_ENABLE_SNAP_START hasn't been set, although the result will always be
1226 +** SSL_SNAP_START_NONE.
1227 +*/
1228 +SSL_IMPORT SECStatus SSL_GetSnapStartResult(PRFileDesc* socket,
1229 + SSLSnapStartResult* result);
1230 +
1231 +/*
1232 ** Configure SSL socket for running a secure server. Needs the
1233 ** certificate for the server and the servers private key. The arguments
1234 ** are copied.
1235 diff --git a/mozilla/security/nss/lib/ssl/ssl3con.c b/mozilla/security/nss/lib/s sl/ssl3con.c
1236 index 64c3452..9ab2a1c 100644
1237 --- a/mozilla/security/nss/lib/ssl/ssl3con.c
1238 +++ b/mozilla/security/nss/lib/ssl/ssl3con.c
1239 @@ -72,7 +72,8 @@
1240 #endif
1241
1242 static void ssl3_CleanupPeerCerts(sslSocket *ss);
1243 -static void ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid);
1244 +static void ssl3_CopyPeerCertsToSID(ssl3CertNode *certs,
1245 + sslSessionID *sid);
1246 static PK11SymKey *ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec,
1247 PK11SlotInfo * serverKeySlot);
1248 static SECStatus ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms);
1249 @@ -82,14 +83,10 @@ static SECStatus ssl3_InitState( sslSocket *ss);
1250 static SECStatus ssl3_SendCertificate( sslSocket *ss);
1251 static SECStatus ssl3_SendEmptyCertificate( sslSocket *ss);
1252 static SECStatus ssl3_SendCertificateRequest(sslSocket *ss);
1253 -static SECStatus ssl3_SendNextProto( sslSocket *ss);
1254 -static SECStatus ssl3_SendFinished( sslSocket *ss, PRInt32 flags);
1255 static SECStatus ssl3_SendServerHello( sslSocket *ss);
1256 static SECStatus ssl3_SendServerHelloDone( sslSocket *ss);
1257 static SECStatus ssl3_SendServerKeyExchange( sslSocket *ss);
1258 static SECStatus ssl3_NewHandshakeHashes( sslSocket *ss);
1259 -static SECStatus ssl3_UpdateHandshakeHashes( sslSocket *ss, unsigned char *b,
1260 - unsigned int l);
1261
1262 static SECStatus Null_Cipher(void *ctx, unsigned char *output, int *outputLen,
1263 int maxOutputLen, const unsigned char *input,
1264 @@ -583,7 +580,7 @@ void SSL_AtomicIncrementLong(long * x)
1265
1266 /* return pointer to ssl3CipherSuiteDef for suite, or NULL */
1267 /* XXX This does a linear search. A binary search would be better. */
1268 -static const ssl3CipherSuiteDef *
1269 +const ssl3CipherSuiteDef *
1270 ssl_LookupCipherSuiteDef(ssl3CipherSuite suite)
1271 {
1272 int cipher_suite_def_len =
1273 @@ -1169,7 +1166,7 @@ ssl3_CleanupKeyMaterial(ssl3KeyMaterial *mat)
1274 ** ssl3_DestroySSL3Info
1275 ** Caller must hold SpecWriteLock.
1276 */
1277 -static void
1278 +void
1279 ssl3_DestroyCipherSpec(ssl3CipherSpec *spec, PRBool freeSrvName)
1280 {
1281 PRBool freeit = (PRBool)(!spec->bypassCiphers);
1282 @@ -1211,7 +1208,7 @@ ssl3_DestroyCipherSpec(ssl3CipherSpec *spec, PRBool freeSr vName)
1283 ** Caller must hold the ssl3 handshake lock.
1284 ** Acquires & releases SpecWriteLock.
1285 */
1286 -static SECStatus
1287 +SECStatus
1288 ssl3_SetupPendingCipherSpec(sslSocket *ss)
1289 {
1290 ssl3CipherSpec * pwSpec;
1291 @@ -2039,7 +2036,7 @@ ssl3_ClientAuthTokenPresent(sslSessionID *sid) {
1292 return isPresent;
1293 }
1294
1295 -static SECStatus
1296 +SECStatus
1297 ssl3_CompressMACEncryptRecord(sslSocket * ss,
1298 SSL3ContentType type,
1299 const SSL3Opaque * pIn,
1300 @@ -3097,7 +3094,7 @@ loser:
1301 return SECFailure;
1302 }
1303
1304 -static SECStatus
1305 +SECStatus
1306 ssl3_RestartHandshakeHashes(sslSocket *ss)
1307 {
1308 SECStatus rv = SECSuccess;
1309 @@ -3175,7 +3172,7 @@ loser:
1310 ** ssl3_HandleHandshakeMessage()
1311 ** Caller must hold the ssl3Handshake lock.
1312 */
1313 -static SECStatus
1314 +SECStatus
1315 ssl3_UpdateHandshakeHashes(sslSocket *ss, unsigned char *b, unsigned int l)
1316 {
1317 SECStatus rv = SECSuccess;
1318 @@ -3434,7 +3431,7 @@ ssl3_ConsumeHandshakeVariable(sslSocket *ss, SECItem *i, P RInt32 bytes,
1319 * Caller must hold a read or write lock on the Spec R/W lock.
1320 * (There is presently no way to assert on a Read lock.)
1321 */
1322 -static SECStatus
1323 +SECStatus
1324 ssl3_ComputeHandshakeHashes(sslSocket * ss,
1325 ssl3CipherSpec *spec, /* uses ->master_secret */
1326 SSL3Hashes * hashes, /* output goes here. */
1327 @@ -4032,7 +4029,18 @@ ssl3_SendClientHello(sslSocket *ss)
1328 return rv; /* error code set by ssl3_FlushHandshake */
1329 }
1330
1331 - ss->ssl3.hs.ws = wait_server_hello;
1332 + switch (ss->ssl3.hs.snapStartType) {
1333 + case snap_start_full:
1334 + ss->ssl3.hs.ws = wait_new_session_ticket;
1335 + break;
1336 + case snap_start_resume:
1337 + ss->ssl3.hs.ws = wait_change_cipher;
1338 + break;
1339 + default:
1340 + ss->ssl3.hs.ws = wait_server_hello;
1341 + break;
1342 + }
1343 +
1344 return rv;
1345 }
1346
1347 @@ -4723,7 +4731,7 @@ loser:
1348
1349
1350 /* Called from ssl3_HandleServerHelloDone(). */
1351 -static SECStatus
1352 +SECStatus
1353 ssl3_SendClientKeyExchange(sslSocket *ss)
1354 {
1355 SECKEYPublicKey * serverKey = NULL;
1356 @@ -4862,6 +4870,94 @@ done:
1357 return rv;
1358 }
1359
1360 +/* Called from ssl3_HandleServerHello to set up the master secret in
1361 + * ss->ssl3.pwSpec and the auth algorithm and kea type in ss->sec in the case
1362 + * of a successful session resumption. */
1363 +SECStatus ssl3_SetupMasterSecretFromSessionID(sslSocket* ss) {
1364 + sslSessionID *sid = ss->sec.ci.sid;
1365 + ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec;
1366 + SECItem wrappedMS; /* wrapped master secret. */
1367 +
1368 + ss->sec.authAlgorithm = sid->authAlgorithm;
1369 + ss->sec.authKeyBits = sid->authKeyBits;
1370 + ss->sec.keaType = sid->keaType;
1371 + ss->sec.keaKeyBits = sid->keaKeyBits;
1372 +
1373 + /* 3 cases here:
1374 + * a) key is wrapped (implies using PKCS11)
1375 + * b) key is unwrapped, but we're still using PKCS11
1376 + * c) key is unwrapped, and we're bypassing PKCS11.
1377 + */
1378 + if (sid->u.ssl3.keys.msIsWrapped) {
1379 + PK11SlotInfo *slot;
1380 + PK11SymKey * wrapKey; /* wrapping key */
1381 + CK_FLAGS keyFlags = 0;
1382 +
1383 + if (ss->opt.bypassPKCS11) {
1384 + /* we cannot restart a non-bypass session in a
1385 + ** bypass socket.
1386 + */
1387 + return SECFailure;
1388 + }
1389 + /* unwrap master secret with PKCS11 */
1390 + slot = SECMOD_LookupSlot(sid->u.ssl3.masterModuleID,
1391 + sid->u.ssl3.masterSlotID);
1392 + if (slot == NULL) {
1393 + return SECFailure;
1394 + }
1395 + if (!PK11_IsPresent(slot)) {
1396 + PK11_FreeSlot(slot);
1397 + return SECFailure;
1398 + }
1399 + wrapKey = PK11_GetWrapKey(slot, sid->u.ssl3.masterWrapIndex,
1400 + sid->u.ssl3.masterWrapMech,
1401 + sid->u.ssl3.masterWrapSeries,
1402 + ss->pkcs11PinArg);
1403 + PK11_FreeSlot(slot);
1404 + if (wrapKey == NULL) {
1405 + return SECFailure;
1406 + }
1407 +
1408 + if (ss->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */
1409 + keyFlags = CKF_SIGN | CKF_VERIFY;
1410 + }
1411 +
1412 + wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
1413 + wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len;
1414 + pwSpec->master_secret =
1415 + PK11_UnwrapSymKeyWithFlags(wrapKey, sid->u.ssl3.masterWrapMech,
1416 + NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE,
1417 + CKA_DERIVE, sizeof(SSL3MasterSecret), keyFlags);
1418 + PK11_FreeSymKey(wrapKey);
1419 + if (pwSpec->master_secret == NULL) {
1420 + return SECFailure;
1421 + }
1422 + } else if (ss->opt.bypassPKCS11) {
1423 + /* MS is not wrapped */
1424 + wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
1425 + wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len;
1426 + memcpy(pwSpec->raw_master_secret, wrappedMS.data, wrappedMS.len);
1427 + pwSpec->msItem.data = pwSpec->raw_master_secret;
1428 + pwSpec->msItem.len = wrappedMS.len;
1429 + } else {
1430 + /* We CAN restart a bypass session in a non-bypass socket. */
1431 + /* need to import the raw master secret to session object */
1432 + PK11SlotInfo *slot = PK11_GetInternalSlot();
1433 + wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
1434 + wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len;
1435 + pwSpec->master_secret =
1436 + PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE,
1437 + PK11_OriginUnwrap, CKA_ENCRYPT,
1438 + &wrappedMS, NULL);
1439 + PK11_FreeSlot(slot);
1440 + if (pwSpec->master_secret == NULL) {
1441 + return SECFailure;
1442 + }
1443 + }
1444 +
1445 + return SECSuccess;
1446 +}
1447 +
1448 /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
1449 * ssl3 ServerHello message.
1450 * Caller must hold Handshake and RecvBuf locks.
1451 @@ -4886,6 +4982,14 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUi nt32 length)
1452 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
1453 PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
1454
1455 + if (ss->ssl3.hs.snapStartType == snap_start_full ||
1456 + ss->ssl3.hs.snapStartType == snap_start_resume) {
1457 + /* Snap Start handshake was rejected. */
1458 + rv = ssl3_ResetForSnapStartRecovery(ss, b, length);
1459 + if (rv != SECSuccess)
1460 + return rv;
1461 + }
1462 +
1463 rv = ssl3_InitState(ss);
1464 if (rv != SECSuccess) {
1465 errCode = PORT_GetError(); /* ssl3_InitState has set the error code. */
1466 @@ -4897,6 +5001,21 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUi nt32 length)
1467 goto alert_loser;
1468 }
1469
1470 + if (!ss->ssl3.serverHelloPredictionData.data) {
1471 + /* If this allocation fails it will only stop the application from
1472 + * recording the ServerHello information and performing future Snap
1473 + * Starts. */
1474 + if (SECITEM_AllocItem(NULL, &ss->ssl3.serverHelloPredictionData,
1475 + length))
1476 + memcpy(ss->ssl3.serverHelloPredictionData.data, b, length);
1477 + /* ss->ssl3.serverHelloPredictionDataValid is still false at this
1478 + * point. We have to record the contents of the ServerHello here
1479 + * because we don't have a pointer to the whole message when handling
1480 + * the extensions. However, we wait until the Snap Start extenion
1481 + * handler to recognise that the server supports Snap Start and to set
1482 + * serverHelloPredictionDataValid. */
1483 + }
1484 +
1485 temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
1486 if (temp < 0) {
1487 goto loser; /* alert has been sent */
1488 @@ -5037,118 +5156,40 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PR Uint32 length)
1489
1490 if (sid_match &&
1491 sid->version == ss->version &&
1492 - sid->u.ssl3.cipherSuite == ss->ssl3.hs.cipher_suite) do {
1493 - ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec;
1494 -
1495 - SECItem wrappedMS; /* wrapped master secret. */
1496 + sid->u.ssl3.cipherSuite == ss->ssl3.hs.cipher_suite) {
1497 + rv = ssl3_SetupMasterSecretFromSessionID(ss);
1498 + /* Failure of ssl3_SetupMasterSecretFromSessionID not considered an
1499 + * error. Continue with a full handshake. */
1500 + if (rv == SECSuccess) {
1501 + /* Got a Match */
1502 + SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_cache_hits );
1503
1504 - ss->sec.authAlgorithm = sid->authAlgorithm;
1505 - ss->sec.authKeyBits = sid->authKeyBits;
1506 - ss->sec.keaType = sid->keaType;
1507 - ss->sec.keaKeyBits = sid->keaKeyBits;
1508 + /* If we sent a session ticket, then this is a stateless resume. */
1509 + if (sid->version > SSL_LIBRARY_VERSION_3_0 &&
1510 + sid->u.ssl3.sessionTicket.ticket.data != NULL)
1511 + SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_stateless_resumes );
1512
1513 - /* 3 cases here:
1514 - * a) key is wrapped (implies using PKCS11)
1515 - * b) key is unwrapped, but we're still using PKCS11
1516 - * c) key is unwrapped, and we're bypassing PKCS11.
1517 - */
1518 - if (sid->u.ssl3.keys.msIsWrapped) {
1519 - PK11SlotInfo *slot;
1520 - PK11SymKey * wrapKey; /* wrapping key */
1521 - CK_FLAGS keyFlags = 0;
1522 + if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn))
1523 + ss->ssl3.hs.ws = wait_new_session_ticket;
1524 + else
1525 + ss->ssl3.hs.ws = wait_change_cipher;
1526
1527 - if (ss->opt.bypassPKCS11) {
1528 - /* we cannot restart a non-bypass session in a
1529 - ** bypass socket.
1530 - */
1531 - break;
1532 - }
1533 - /* unwrap master secret with PKCS11 */
1534 - slot = SECMOD_LookupSlot(sid->u.ssl3.masterModuleID,
1535 - sid->u.ssl3.masterSlotID);
1536 - if (slot == NULL) {
1537 - break; /* not considered an error. */
1538 - }
1539 - if (!PK11_IsPresent(slot)) {
1540 - PK11_FreeSlot(slot);
1541 - break; /* not considered an error. */
1542 - }
1543 - wrapKey = PK11_GetWrapKey(slot, sid->u.ssl3.masterWrapIndex,
1544 - sid->u.ssl3.masterWrapMech,
1545 - sid->u.ssl3.masterWrapSeries,
1546 - ss->pkcs11PinArg);
1547 - PK11_FreeSlot(slot);
1548 - if (wrapKey == NULL) {
1549 - break; /* not considered an error. */
1550 - }
1551 + ss->ssl3.hs.isResuming = PR_TRUE;
1552
1553 - if (ss->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */
1554 - keyFlags = CKF_SIGN | CKF_VERIFY;
1555 + /* copy the peer cert from the SID */
1556 + if (sid->peerCert != NULL) {
1557 + ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
1558 + ssl3_CopyPeerCertsFromSID(ss, sid);
1559 }
1560
1561 - wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
1562 - wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len;
1563 - pwSpec->master_secret =
1564 - PK11_UnwrapSymKeyWithFlags(wrapKey, sid->u.ssl3.masterWrapMech,
1565 - NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE,
1566 - CKA_DERIVE, sizeof(SSL3MasterSecret), keyFlags);
1567 - errCode = PORT_GetError();
1568 - PK11_FreeSymKey(wrapKey);
1569 - if (pwSpec->master_secret == NULL) {
1570 - break; /* errorCode set just after call to UnwrapSymKey. */
1571 - }
1572 - } else if (ss->opt.bypassPKCS11) {
1573 - /* MS is not wrapped */
1574 - wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
1575 - wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len;
1576 - memcpy(pwSpec->raw_master_secret, wrappedMS.data, wrappedMS.len);
1577 - pwSpec->msItem.data = pwSpec->raw_master_secret;
1578 - pwSpec->msItem.len = wrappedMS.len;
1579 - } else {
1580 - /* We CAN restart a bypass session in a non-bypass socket. */
1581 - /* need to import the raw master secret to session object */
1582 - PK11SlotInfo *slot = PK11_GetInternalSlot();
1583 - wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;
1584 - wrappedMS.len = sid->u.ssl3.keys.wrapped_master_secret_len;
1585 - pwSpec->master_secret =
1586 - PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE,
1587 - PK11_OriginUnwrap, CKA_ENCRYPT,
1588 - &wrappedMS, NULL);
1589 - PK11_FreeSlot(slot);
1590 - if (pwSpec->master_secret == NULL) {
1591 - break;
1592 + /* NULL value for PMS signifies re-use of the old MS */
1593 + rv = ssl3_InitPendingCipherSpec(ss, NULL);
1594 + if (rv != SECSuccess) {
1595 + goto alert_loser;
1596 }
1597 + return SECSuccess;
1598 }
1599 -
1600 - /* Got a Match */
1601 - SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_cache_hits );
1602 -
1603 - /* If we sent a session ticket, then this is a stateless resume. */
1604 - if (sid->version > SSL_LIBRARY_VERSION_3_0 &&
1605 - sid->u.ssl3.sessionTicket.ticket.data != NULL)
1606 - SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_stateless_resumes );
1607 -
1608 - if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn))
1609 - ss->ssl3.hs.ws = wait_new_session_ticket;
1610 - else
1611 - ss->ssl3.hs.ws = wait_change_cipher;
1612 -
1613 - ss->ssl3.hs.isResuming = PR_TRUE;
1614 -
1615 - /* copy the peer cert from the SID */
1616 - if (sid->peerCert != NULL) {
1617 - ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
1618 - ssl3_CopyPeerCertsFromSID(ss, sid);
1619 - }
1620 -
1621 -
1622 - /* NULL value for PMS signifies re-use of the old MS */
1623 - rv = ssl3_InitPendingCipherSpec(ss, NULL);
1624 - if (rv != SECSuccess) {
1625 - goto alert_loser; /* err code was set */
1626 - }
1627 - return SECSuccess;
1628 - } while (0);
1629 + }
1630
1631 if (sid_match)
1632 SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_cache_not_ok );
1633 @@ -6116,7 +6157,7 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUin t32 length)
1634 * ticket extension, but sent an empty ticket.
1635 */
1636 if (!ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn) ||
1637 - ss->xtnData.emptySessionTicket) {
1638 + ss->xtnData.serverReceivedEmptySessionTicket) {
1639 if (sidBytes.len > 0 && !ss->opt.noCache) {
1640 SSL_TRC(7, ("%d: SSL3[%d]: server, lookup client session-id for 0x%0 8x%08x%08x%08x",
1641 SSL_GETPID(), ss->fd, ss->sec.ci.peer.pr_s6_addr32[0],
1642 @@ -7569,6 +7610,12 @@ ssl3_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
1643 return SECFailure; /* malformed */
1644 }
1645
1646 + if (ss->sec.ci.sid->peerCert == NULL) {
1647 + ss->sec.ci.sid->peerCert = CERT_DupCertificate(ss->sec.peerCert);
1648 + ssl3_CopyPeerCertsToSID((ssl3CertNode *)ss->ssl3.peerCertChain,
1649 + ss->sec.ci.sid);
1650 + }
1651 +
1652 rv = ssl3_SetSIDSessionTicket(ss->sec.ci.sid, &session_ticket);
1653 if (rv != SECSuccess) {
1654 (void)SSL3_SendAlert(ss, alert_fatal, handshake_failure);
1655 @@ -7760,7 +7807,7 @@ ssl3_CleanupPeerCerts(sslSocket *ss)
1656 ss->ssl3.peerCertChain = NULL;
1657 }
1658
1659 -static void
1660 +void
1661 ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid)
1662 {
1663 PRArenaPool *arena;
1664 @@ -8163,7 +8210,7 @@ ssl3_RestartHandshakeAfterServerCert(sslSocket *ss)
1665 return rv;
1666 }
1667
1668 -static SECStatus
1669 +SECStatus
1670 ssl3_ComputeTLSFinished(ssl3CipherSpec *spec,
1671 PRBool isServer,
1672 const SSL3Finished * hashes,
1673 @@ -8211,7 +8258,7 @@ ssl3_ComputeTLSFinished(ssl3CipherSpec *spec,
1674
1675 /* called from ssl3_HandleServerHelloDone
1676 */
1677 -static SECStatus
1678 +SECStatus
1679 ssl3_SendNextProto(sslSocket *ss)
1680 {
1681 SECStatus rv;
1682 @@ -8247,7 +8294,7 @@ ssl3_SendNextProto(sslSocket *ss)
1683 * ssl3_HandleClientHello
1684 * ssl3_HandleFinished
1685 */
1686 -static SECStatus
1687 +SECStatus
1688 ssl3_SendFinished(sslSocket *ss, PRInt32 flags)
1689 {
1690 ssl3CipherSpec *cwSpec;
1691 @@ -8300,10 +8347,27 @@ ssl3_SendFinished(sslSocket *ss, PRInt32 flags)
1692 if (rv != SECSuccess)
1693 goto fail; /* err set by AppendHandshake. */
1694 }
1695 - rv = ssl3_FlushHandshake(ss, flags);
1696 - if (rv != SECSuccess) {
1697 - goto fail; /* error code set by ssl3_FlushHandshake */
1698 + if ((flags & ssl_SEND_FLAG_NO_FLUSH) == 0) {
1699 + rv = ssl3_FlushHandshake(ss, flags);
1700 + if (rv != SECSuccess) {
1701 + goto fail; /* error code set by ssl3_FlushHandshake */
1702 + }
1703 }
1704 +
1705 + if ((ss->ssl3.hs.snapStartType == snap_start_recovery ||
1706 + ss->ssl3.hs.snapStartType == snap_start_resume_recovery) &&
1707 + ss->ssl3.snapStartApplicationData.data) {
1708 + /* In the event that the server ignored the application data in our
1709 + * snap start extension, we need to retransmit it now. */
1710 + PRInt32 sent = ssl3_SendRecord(ss, content_application_data,
1711 + ss->ssl3.snapStartApplicationData.data,
1712 + ss->ssl3.snapStartApplicationData.len,
1713 + flags);
1714 + SECITEM_FreeItem(&ss->ssl3.snapStartApplicationData, PR_FALSE);
1715 + if (sent < 0)
1716 + return (SECStatus)sent; /* error code set by ssl3_SendRecord */
1717 + }
1718 +
1719 return SECSuccess;
1720
1721 fail:
1722 @@ -8420,6 +8484,16 @@ ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint3 2 length,
1723 return SECFailure;
1724 }
1725
1726 + if (ss->ssl3.hs.snapStartType == snap_start_full ||
1727 + ss->ssl3.hs.snapStartType == snap_start_resume) {
1728 + /* Snap Start handshake was successful. Switch the cipher spec. */
1729 + ssl_GetSpecWriteLock(ss);
1730 + ssl3_DestroyCipherSpec(ss->ssl3.cwSpec, PR_TRUE/*freeSrvName*/);
1731 + ss->ssl3.cwSpec = ss->ssl3.pwSpec;
1732 + ss->ssl3.pwSpec = NULL;
1733 + ssl_ReleaseSpecWriteLock(ss);
1734 + }
1735 +
1736 isTLS = (PRBool)(ss->ssl3.crSpec->version > SSL_LIBRARY_VERSION_3_0);
1737 if (isTLS) {
1738 TLSFinished tlsFinished;
1739 @@ -8429,12 +8503,21 @@ ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint 32 length,
1740 PORT_SetError(SSL_ERROR_RX_MALFORMED_FINISHED);
1741 return SECFailure;
1742 }
1743 - rv = ssl3_ComputeTLSFinished(ss->ssl3.crSpec, !isServer,
1744 - hashes, &tlsFinished);
1745 - if (!isServer)
1746 - ss->ssl3.hs.finishedMsgs.tFinished[1] = tlsFinished;
1747 - else
1748 - ss->ssl3.hs.finishedMsgs.tFinished[0] = tlsFinished;
1749 +
1750 + if (ss->ssl3.hs.snapStartType == snap_start_resume) {
1751 + /* In this case we have already advanced the Finished hash past the
1752 + * server's verify_data because we needed to predict the server's
1753 + * Finished message in order to compute our own (which includes
1754 + * it). When we did this, we stored a copy in tFinished[1]. */
1755 + tlsFinished = ss->ssl3.hs.finishedMsgs.tFinished[1];
1756 + } else {
1757 + rv = ssl3_ComputeTLSFinished(ss->ssl3.crSpec, !isServer,
1758 + hashes, &tlsFinished);
1759 + if (!isServer)
1760 + ss->ssl3.hs.finishedMsgs.tFinished[1] = tlsFinished;
1761 + else
1762 + ss->ssl3.hs.finishedMsgs.tFinished[0] = tlsFinished;
1763 + }
1764 ss->ssl3.hs.finishedBytes = sizeof tlsFinished;
1765 if (rv != SECSuccess ||
1766 0 != NSS_SecureMemcmp(&tlsFinished, b, length)) {
1767 @@ -8465,8 +8548,9 @@ ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
1768
1769 ssl_GetXmitBufLock(ss); /*************************************/
1770
1771 - if ((isServer && !ss->ssl3.hs.isResuming) ||
1772 - (!isServer && ss->ssl3.hs.isResuming)) {
1773 + if (ss->ssl3.hs.snapStartType != snap_start_resume &&
1774 + ((isServer && !ss->ssl3.hs.isResuming) ||
1775 + (!isServer && ss->ssl3.hs.isResuming))) {
1776 PRInt32 flags = 0;
1777
1778 /* Send a NewSessionTicket message if the client sent us
1779 @@ -8582,7 +8666,10 @@ xmit_loser:
1780 ss->ssl3.hs.ws = idle_handshake;
1781
1782 /* Do the handshake callback for sslv3 here, if we cannot false start. */
1783 - if (ss->handshakeCallback != NULL && !ssl3_CanFalseStart(ss)) {
1784 + if (ss->handshakeCallback != NULL &&
1785 + (!ssl3_CanFalseStart(ss) ||
1786 + ss->ssl3.hs.snapStartType == snap_start_full ||
1787 + ss->ssl3.hs.snapStartType == snap_start_resume)) {
1788 (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
1789 }
1790
1791 @@ -8643,8 +8730,13 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
1792 return rv;
1793 }
1794 }
1795 - /* We should not include hello_request messages in the handshake hashes */
1796 - if (ss->ssl3.hs.msg_type != hello_request) {
1797 + /* We should not include hello_request messages in the handshake hashes.
1798 + * Likewise, for Finished messages from the server during a Snap Start
1799 + * resume, we have already predicted and included the message in our
1800 + * Finished hash. */
1801 + if (ss->ssl3.hs.msg_type != hello_request &&
1802 + !(ss->ssl3.hs.msg_type == finished &&
1803 + ss->ssl3.hs.snapStartType == snap_start_resume)) {
1804 rv = ssl3_UpdateHandshakeHashes(ss, (unsigned char*) hdr, 4);
1805 if (rv != SECSuccess) return rv; /* err code already set. */
1806 rv = ssl3_UpdateHandshakeHashes(ss, b, length);
1807 @@ -9545,6 +9637,15 @@ ssl3_DestroySSL3Info(sslSocket *ss)
1808 ss->ssl3.clientCertChain = NULL;
1809 }
1810
1811 + if (ss->ssl3.predictedCertChain != NULL)
1812 + ssl3_CleanupPredictedPeerCertificates(ss);
1813 +
1814 + if (ss->ssl3.serverHelloPredictionData.data)
1815 + SECITEM_FreeItem(&ss->ssl3.serverHelloPredictionData, PR_FALSE);
1816 +
1817 + if (ss->ssl3.snapStartApplicationData.data)
1818 + SECITEM_FreeItem(&ss->ssl3.snapStartApplicationData, PR_FALSE);
1819 +
1820 /* clean up handshake */
1821 if (ss->opt.bypassPKCS11) {
1822 SHA1_DestroyContext((SHA1Context *)ss->ssl3.hs.sha_cx, PR_FALSE);
1823 @@ -9562,6 +9663,9 @@ ssl3_DestroySSL3Info(sslSocket *ss)
1824 ss->ssl3.hs.messages.len = 0;
1825 ss->ssl3.hs.messages.space = 0;
1826 }
1827 + if (ss->ssl3.hs.origClientHello.data) {
1828 + SECITEM_FreeItem(&ss->ssl3.hs.origClientHello, PR_FALSE);
1829 + }
1830
1831 /* free the SSL3Buffer (msg_body) */
1832 PORT_Free(ss->ssl3.hs.msg_body.buf);
1833 diff --git a/mozilla/security/nss/lib/ssl/ssl3ext.c b/mozilla/security/nss/lib/s sl/ssl3ext.c
1834 index fbd5a91..a7ae062 100644
1835 --- a/mozilla/security/nss/lib/ssl/ssl3ext.c
1836 +++ b/mozilla/security/nss/lib/ssl/ssl3ext.c
1837 @@ -247,6 +247,7 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTL S[] = {
1838 { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn },
1839 { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
1840 { ssl_next_proto_neg_xtn, &ssl3_ClientHandleNextProtoNegoXtn },
1841 + { ssl_snap_start_xtn, &ssl3_ClientHandleSnapStartXtn },
1842 { -1, NULL }
1843 };
1844
1845 @@ -270,7 +271,9 @@ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTEN SIONS] = {
1846 { ssl_ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn },
1847 #endif
1848 { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn },
1849 - { ssl_next_proto_neg_xtn, &ssl3_ClientSendNextProtoNegoXtn }
1850 + { ssl_next_proto_neg_xtn, &ssl3_ClientSendNextProtoNegoXtn },
1851 + { ssl_snap_start_xtn, &ssl3_SendSnapStartXtn }
1852 + /* NOTE: The Snap Start sender MUST be the last extension in the list. */
1853 /* any extra entries will appear as { 0, NULL } */
1854 };
1855
1856 @@ -298,7 +301,7 @@ ssl3_ExtensionNegotiated(sslSocket *ss, PRUint16 ex_type) {
1857 xtnData->numNegotiated, ex_type);
1858 }
1859
1860 -static PRBool
1861 +PRBool
1862 ssl3_ClientExtensionAdvertised(sslSocket *ss, PRUint16 ex_type) {
1863 TLSExtensionData *xtnData = &ss->xtnData;
1864 return arrayContainsExtension(xtnData->advertised,
1865 @@ -515,6 +518,8 @@ ssl3_SendSessionTicketXtn(
1866 rv = ssl3_AppendHandshakeVariable(ss, session_ticket->ticket.data,
1867 session_ticket->ticket.len, 2);
1868 ss->xtnData.ticketTimestampVerified = PR_FALSE;
1869 + if (!ss->sec.isServer)
1870 + ss->xtnData.clientSentNonEmptySessionTicket = PR_TRUE;
1871 } else {
1872 rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
1873 }
1874 @@ -573,7 +578,7 @@ ssl3_ValidateNextProtoNego(const unsigned char* data, unsign ed short length)
1875
1876 SECStatus
1877 ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type,
1878 - SECItem *data)
1879 + SECItem *data)
1880 {
1881 unsigned int i, j;
1882 SECStatus rv;
1883 @@ -1021,7 +1026,7 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
1884 * instead of terminating the current connection.
1885 */
1886 if (data->len == 0) {
1887 - ss->xtnData.emptySessionTicket = PR_TRUE;
1888 + ss->xtnData.serverReceivedEmptySessionTicket = PR_TRUE;
1889 } else {
1890 int i;
1891 SECItem extension_data;
1892 diff --git a/mozilla/security/nss/lib/ssl/sslimpl.h b/mozilla/security/nss/lib/s sl/sslimpl.h
1893 index fe7ac7a..f708696 100644
1894 --- a/mozilla/security/nss/lib/ssl/sslimpl.h
1895 +++ b/mozilla/security/nss/lib/ssl/sslimpl.h
1896 @@ -278,6 +278,7 @@ struct sslSocketOpsStr {
1897 /* Flags interpreted by ssl send functions. */
1898 #define ssl_SEND_FLAG_FORCE_INTO_BUFFER 0x40000000
1899 #define ssl_SEND_FLAG_NO_BUFFER 0x20000000
1900 +#define ssl_SEND_FLAG_NO_FLUSH 0x10000000
1901 #define ssl_SEND_FLAG_MASK 0x7f000000
1902
1903 /*
1904 @@ -339,6 +340,7 @@ typedef struct sslOptionsStr {
1905 unsigned int enableRenegotiation : 2; /* 20-21 */
1906 unsigned int requireSafeNegotiation : 1; /* 22 */
1907 unsigned int enableFalseStart : 1; /* 23 */
1908 + unsigned int enableSnapStart : 1; /* 24 */
1909 } sslOptions;
1910
1911 typedef enum { sslHandshakingUndetermined = 0,
1912 @@ -743,7 +745,8 @@ struct TLSExtensionDataStr {
1913
1914 /* SessionTicket Extension related data. */
1915 PRBool ticketTimestampVerified;
1916 - PRBool emptySessionTicket;
1917 + PRBool serverReceivedEmptySessionTicket;
1918 + PRBool clientSentNonEmptySessionTicket;
1919
1920 /* SNI Extension related data
1921 * Names data is not coppied from the input buffer. It can not be
1922 @@ -753,6 +756,14 @@ struct TLSExtensionDataStr {
1923 PRUint32 sniNameArrSize;
1924 };
1925
1926 +typedef enum {
1927 + snap_start_none = 0,
1928 + snap_start_full,
1929 + snap_start_recovery,
1930 + snap_start_resume,
1931 + snap_start_resume_recovery
1932 +} TLSSnapStartType;
1933 +
1934 /*
1935 ** This is the "hs" member of the "ssl3" struct.
1936 ** This entire struct is protected by ssl3HandshakeLock
1937 @@ -791,6 +802,14 @@ const ssl3CipherSuiteDef *suite_def;
1938 SSL3Hashes sFinished[2];
1939 SSL3Opaque data[72];
1940 } finishedMsgs;
1941 +
1942 + TLSSnapStartType snapStartType;
1943 + /* When we perform a Snap Start handshake, we hash our ClientHello as if
1944 + * the Snap Start extension wasn't included. However, if the server rejects
1945 + * our Snap Start attempt, then it will hash the whole ClientHello. Thus we
1946 + * store the original ClientHello that we sent in case we need to reset our
1947 + * Finished hash to cover it. */
1948 + SECItem origClientHello;
1949 #ifdef NSS_ENABLE_ECC
1950 PRUint32 negotiatedECCurves; /* bit mask */
1951 #endif /* NSS_ENABLE_ECC */
1952 @@ -823,6 +842,17 @@ struct ssl3StateStr {
1953 CERTCertificateList *clientCertChain; /* used by client */
1954 PRBool sendEmptyCert; /* used by client */
1955
1956 + /* TLS Snap Start: */
1957 + CERTCertificate ** predictedCertChain;
1958 + /* An array terminated with a NULL. */
1959 + SECItem serverHelloPredictionData;
1960 + PRBool serverHelloPredictionDataValid;
1961 + /* data needed to predict the ServerHello from
1962 + * this server. */
1963 + SECItem snapStartApplicationData;
1964 + /* the application data to include in the Snap
1965 + * Start extension. */
1966 +
1967 int policy;
1968 /* This says what cipher suites we can do, and should
1969 * be either SSL_ALLOWED or SSL_RESTRICTED
1970 @@ -1258,10 +1288,13 @@ extern sslSessionID *ssl3_NewSessionID(sslSocket *ss, PR Bool is_server);
1971 extern sslSessionID *ssl_LookupSID(const PRIPv6Addr *addr, PRUint16 port,
1972 const char *peerID, const char *urlSvrName);
1973 extern void ssl_FreeSID(sslSessionID *sid);
1974 +extern void ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid);
1975
1976 extern int ssl3_SendApplicationData(sslSocket *ss, const PRUint8 *in,
1977 int len, int flags);
1978
1979 +extern SECStatus ssl3_RestartHandshakeHashes(sslSocket *ss);
1980 +
1981 extern PRBool ssl_FdIsBlocking(PRFileDesc *fd);
1982
1983 extern PRBool ssl_SocketIsBlocking(sslSocket *ss);
1984 @@ -1434,6 +1467,9 @@ ECName ssl3_GetCurveWithECKeyStrength(PRUint32 curvemsk , int requiredECCbits);
1985
1986 #endif /* NSS_ENABLE_ECC */
1987
1988 +extern SECStatus ssl3_UpdateHandshakeHashes(sslSocket* ss, unsigned char *b,
1989 + unsigned int l);
1990 +
1991 extern SECStatus ssl3_CipherPrefSetDefault(ssl3CipherSuite which, PRBool on);
1992 extern SECStatus ssl3_CipherPrefGetDefault(ssl3CipherSuite which, PRBool *on);
1993 extern SECStatus ssl2_CipherPrefSetDefault(PRInt32 which, PRBool enabled);
1994 @@ -1454,6 +1490,7 @@ extern void ssl3_InitSocketPolicy(sslSocket *ss);
1995
1996 extern SECStatus ssl3_ConstructV2CipherSpecsHack(sslSocket *ss,
1997 unsigned char *cs, int *size);
1998 +extern void ssl3_DestroyCipherSpec(ssl3CipherSpec* spec, PRBool freeSrvName);
1999
2000 extern SECStatus ssl3_RedoHandshake(sslSocket *ss, PRBool flushCache);
2001
2002 @@ -1503,6 +1540,31 @@ extern SECStatus ssl3_VerifySignedHashes(SSL3Hashes *hash ,
2003 extern SECStatus ssl3_CacheWrappedMasterSecret(sslSocket *ss,
2004 sslSessionID *sid, ssl3CipherSpec *spec,
2005 SSL3KEAType effectiveExchKeyType);
2006 +extern void ssl3_CleanupPredictedPeerCertificates(sslSocket *ss);
2007 +extern const ssl3CipherSuiteDef* ssl_LookupCipherSuiteDef(ssl3CipherSuite suite );
2008 +extern SECStatus ssl3_SetupPendingCipherSpec(sslSocket *ss);
2009 +extern SECStatus ssl3_SendClientKeyExchange(sslSocket *ss);
2010 +extern SECStatus ssl3_SendNextProto(sslSocket *ss);
2011 +extern SECStatus ssl3_SendFinished(sslSocket *ss, PRInt32 flags);
2012 +extern SECStatus ssl3_CompressMACEncryptRecord
2013 + (sslSocket * ss,
2014 + SSL3ContentType type,
2015 + const SSL3Opaque * pIn,
2016 + PRUint32 contentLen);
2017 +extern PRBool ssl3_ClientExtensionAdvertised(sslSocket *ss, PRUint16 ex_type);
2018 +extern SECStatus ssl3_SetupMasterSecretFromSessionID(sslSocket* ss);
2019 +extern SECStatus ssl3_ComputeHandshakeHashes(
2020 + sslSocket * ss,
2021 + ssl3CipherSpec *spec, /* uses ->master_secret */
2022 + SSL3Hashes * hashes, /* output goes here. */
2023 + PRUint32 sender);
2024 +extern SECStatus ssl3_UpdateHandshakeHashes(sslSocket* ss, unsigned char *b,
2025 + unsigned int l);
2026 +extern SECStatus ssl3_ComputeTLSFinished(
2027 + ssl3CipherSpec *spec,
2028 + PRBool isServer,
2029 + const SSL3Finished * hashes,
2030 + TLSFinished * tlsFinished);
2031
2032 /* Functions that handle ClientHello and ServerHello extensions. */
2033 extern SECStatus ssl3_HandleServerNameXtn(sslSocket * ss,
2034 @@ -1532,6 +1594,13 @@ extern PRInt32 ssl3_SendSessionTicketXtn(sslSocket *ss, P RBool append,
2035 */
2036 extern PRInt32 ssl3_SendServerNameXtn(sslSocket *ss, PRBool append,
2037 PRUint32 maxBytes);
2038 +extern PRInt32 ssl3_SendSnapStartXtn(sslSocket *ss, PRBool append,
2039 + PRUint32 maxBytes);
2040 +extern SECStatus ssl3_ClientHandleSnapStartXtn(sslSocket *ss, PRUint16 ex_type,
2041 + SECItem *data);
2042 +
2043 +extern SECStatus ssl3_ResetForSnapStartRecovery(sslSocket *ss,
2044 + SSL3Opaque *b, PRUint32 length);
2045
2046 /* Assigns new cert, cert chain and keys to ss->serverCerts
2047 * struct. If certChain is NULL, tries to find one. Aborts if
2048 @@ -1635,6 +1704,12 @@ SECStatus SSL_DisableDefaultExportCipherSuites(void);
2049 SECStatus SSL_DisableExportCipherSuites(PRFileDesc * fd);
2050 PRBool SSL_IsExportCipherSuite(PRUint16 cipherSuite);
2051
2052 +/********************** FNV hash *********************/
2053 +
2054 +void FNV1A64_Init(PRUint64 *digest);
2055 +void FNV1A64_Update(PRUint64 *digest, const unsigned char *data,
2056 + unsigned int length);
2057 +void FNV1A64_Final(PRUint64 *digest);
2058
2059 #ifdef TRACE
2060 #define SSL_TRACE(msg) ssl_Trace msg
2061 diff --git a/mozilla/security/nss/lib/ssl/sslsock.c b/mozilla/security/nss/lib/s sl/sslsock.c
2062 index ca0d714..2898b88 100644
2063 --- a/mozilla/security/nss/lib/ssl/sslsock.c
2064 +++ b/mozilla/security/nss/lib/ssl/sslsock.c
2065 @@ -738,6 +738,10 @@ SSL_OptionSet(PRFileDesc *fd, PRInt32 which, PRBool on)
2066 ss->opt.enableFalseStart = on;
2067 break;
2068
2069 + case SSL_ENABLE_SNAP_START:
2070 + ss->opt.enableSnapStart = on;
2071 + break;
2072 +
2073 default:
2074 PORT_SetError(SEC_ERROR_INVALID_ARGS);
2075 rv = SECFailure;
2076 @@ -802,6 +806,7 @@ SSL_OptionGet(PRFileDesc *fd, PRInt32 which, PRBool *pOn)
2077 case SSL_REQUIRE_SAFE_NEGOTIATION:
2078 on = ss->opt.requireSafeNegotiation; break;
2079 case SSL_ENABLE_FALSE_START: on = ss->opt.enableFalseStart; break;
2080 + case SSL_ENABLE_SNAP_START: on = ss->opt.enableSnapStart; break;
2081
2082 default:
2083 PORT_SetError(SEC_ERROR_INVALID_ARGS);
2084 @@ -853,6 +858,7 @@ SSL_OptionGetDefault(PRInt32 which, PRBool *pOn)
2085 on = ssl_defaults.requireSafeNegotiation;
2086 break;
2087 case SSL_ENABLE_FALSE_START: on = ssl_defaults.enableFalseStart; break;
2088 + case SSL_ENABLE_SNAP_START: on = ssl_defaults.enableSnapStart; break;
2089
2090 default:
2091 PORT_SetError(SEC_ERROR_INVALID_ARGS);
2092 @@ -1000,6 +1006,10 @@ SSL_OptionSetDefault(PRInt32 which, PRBool on)
2093 ssl_defaults.enableFalseStart = on;
2094 break;
2095
2096 + case SSL_ENABLE_SNAP_START:
2097 + ssl_defaults.enableSnapStart = on;
2098 + break;
2099 +
2100 default:
2101 PORT_SetError(SEC_ERROR_INVALID_ARGS);
2102 return SECFailure;
2103 diff --git a/mozilla/security/nss/lib/ssl/sslt.h b/mozilla/security/nss/lib/ssl/ sslt.h
2104 index f6e0b62..68cbf87 100644
2105 --- a/mozilla/security/nss/lib/ssl/sslt.h
2106 +++ b/mozilla/security/nss/lib/ssl/sslt.h
2107 @@ -204,9 +204,23 @@ typedef enum {
2108 #endif
2109 ssl_session_ticket_xtn = 35,
2110 ssl_next_proto_neg_xtn = 13172,
2111 + ssl_snap_start_xtn = 13174,
2112 ssl_renegotiation_info_xtn = 0xff01 /* experimental number */
2113 } SSLExtensionType;
2114
2115 -#define SSL_MAX_EXTENSIONS 6
2116 +#define SSL_MAX_EXTENSIONS 7
2117 +
2118 +typedef enum {
2119 + /* No Snap Start handshake was attempted. */
2120 + SSL_SNAP_START_NONE = 0,
2121 + /* A Snap Start full handshake was completed. */
2122 + SSL_SNAP_START_FULL = 1,
2123 + /* A Snap Start full handshake was attempted, but failed. */
2124 + SSL_SNAP_START_RECOVERY = 2,
2125 + /* A Snap Start resume handshake was completed. */
2126 + SSL_SNAP_START_RESUME = 3,
2127 + /* A Snap Start resume handshake was attempted, but failed. */
2128 + SSL_SNAP_START_RESUME_RECOVERY = 4
2129 +} SSLSnapStartResult;
2130
2131 #endif /* __sslt_h_ */
OLDNEW
« no previous file with comments | « net/third_party/nss/patches/applypatches.sh ('k') | net/third_party/nss/patches/snapstart2.patch » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698