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

Side by Side Diff: net/third_party/nss/ssl/snapstart.c

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
« no previous file with comments | « net/third_party/nss/ssl/fnv1a64.c ('k') | net/third_party/nss/ssl/ssl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * TLS Snap Start
3 *
4 * ***** BEGIN LICENSE BLOCK *****
5 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 *
7 * The contents of this file are subject to the Mozilla Public License Version
8 * 1.1 (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 * http://www.mozilla.org/MPL/
11 *
12 * Software distributed under the License is distributed on an "AS IS" basis,
13 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 * for the specific language governing rights and limitations under the
15 * License.
16 *
17 * The Original Code is the Netscape security libraries.
18 *
19 * The Initial Developer of the Original Code is
20 * Netscape Communications Corporation.
21 * Portions created by the Initial Developer are Copyright (C) 1994-2000
22 * the Initial Developer. All Rights Reserved.
23 *
24 * Contributor(s):
25 * Adam Langley, Google Inc.
26 *
27 * Alternatively, the contents of this file may be used under the terms of
28 * either the GNU General Public License Version 2 or later (the "GPL"), or
29 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
38 *
39 * ***** END LICENSE BLOCK ***** */
40
41 /* $Id: ssl3snap.c,v 1.0 2010/08/09 13:00:00 agl%google.com Exp $ */
42
43
44 /* TODO(agl): Refactor ssl3_CompressMACEncryptRecord so that it can write to
45 ** |sendBuf| directly and fix ssl3_AppendSnapStartHandshakeRecord and
46 ** ssl3_AppendSnapStartApplicationData.
47 */
48
49 /* TODO(agl): Add support for snap starting with compression. */
50
51 #include "pk11pub.h"
52 #include "ssl.h"
53 #include "sslimpl.h"
54 #include "sslproto.h"
55
56 static unsigned int GetBE16(const void *in)
57 {
58 const unsigned char *p = in;
59 return ((unsigned) p[0]) << 8 |
60 p[1];
61 }
62
63 static unsigned int GetBE24(const void *in)
64 {
65 const unsigned char *p = in;
66 return ((unsigned) p[0]) << 16 |
67 ((unsigned) p[1]) << 8 |
68 p[2];
69 }
70
71 static void PutBE16(void *out, unsigned int value)
72 {
73 unsigned char *p = out;
74 p[0] = value >> 8;
75 p[1] = value;
76 }
77
78 static void PutBE24(void *out, unsigned int value)
79 {
80 unsigned char *p = out;
81 p[0] = value >> 16;
82 p[1] = value >> 8;
83 p[2] = value;
84 }
85
86 /* ssl3_ForEachExtension calls a callback for each TLS extension in |extensions|
87 ** extensions: points to a block of extensions which includes the two prefix
88 ** length bytes
89 ** is_resuming: if true, certain extensions will be omitted
90 ** f: a function which is called with the data of each extension, which
91 ** includes the four type and length bytes at the beginning.
92 */
93 static PRBool
94 ssl3_ForEachExtension(const SECItem *extensions, PRBool is_resuming,
95 void (*f) (const unsigned char *data, unsigned int length,
96 void *ctx),
97 void *ctx) {
98 unsigned int extensions_len, offset;
99
100 if (extensions->len == 0)
101 return PR_TRUE;
102
103 if (extensions->len < 2)
104 goto loser;
105
106 extensions_len = GetBE16(extensions->data);
107 offset = 2;
108
109 if (extensions->len != 2 + extensions_len)
110 goto loser;
111
112 while (extensions_len) {
113 unsigned int extension_num, extension_len;
114
115 if (extensions->len - offset < 4)
116 goto loser;
117
118 extension_num = GetBE16(extensions->data + offset);
119 extension_len = GetBE16(extensions->data + offset + 2);
120
121 if (extensions->len - offset < 4 + extension_len)
122 goto loser;
123
124 /* When resuming, the server will omit some extensions from the
125 * previous non-resume ServerHello. */
126 if (!is_resuming ||
127 (extension_num != ssl_server_name_xtn &&
128 extension_num != ssl_session_ticket_xtn)) {
129 f(extensions->data + offset, 4 + extension_len, ctx);
130 }
131
132 offset += 4 + extension_len;
133 extensions_len -= 4 + extension_len;
134 }
135
136 return PR_TRUE;
137
138 loser:
139 PORT_SetError(SEC_ERROR_INPUT_LEN);
140 return PR_FALSE;
141 }
142
143 static void
144 ssl3_AccumlateLengths(const unsigned char *data, unsigned int length, void *ptr)
145 {
146 unsigned int *sum = (unsigned int *) ptr;
147 *sum += length;
148 }
149
150 /* ssl3_PredictServerResponse predicts the contents of the server's
151 ** ServerHello...ServerHelloDone (inclusive) and progressively calls a callback
152 ** with the contents of those messages.
153 ** previous_server_hello: the contents of a previous ServerHello from the
154 ** server where the 'random' field has been replaced with our suggested
155 ** server random.
156 ** is_resuming: if false, Certificate and ServerHelloDone messages will be
157 ** predicted
158 ** hashUpdate: a callback which is called repeated with the contents of the
159 ** predicted messages.
160 */
161 static PRBool
162 ssl3_PredictServerResponse(
163 sslSocket *ss, SECItem *previous_server_hello, PRBool is_resuming,
164 void (*hashUpdate) (const unsigned char *data, unsigned int length,
165 void *ctx),
166 void *ctx) {
167 unsigned int old_session_id_length, old_extensions_len;
168 unsigned int extensions_len, server_hello_len;
169 unsigned char session_id_len, header[4];
170 SECItem extensions;
171
172 /* Keep the structure of a ServerHello in mind when reading the following:
173 *
174 * struct ServerHello {
175 * uint16_t version;
176 * uint8_t random[32];
177 * uint8_t session_id_len;
178 * uint8_t session_id[session_id_len];
179 * uint16_t cipher
180 * uint8_t compression
181 *
182 * // Optional:
183 * uint16_t extensions_len;
184 * struct Extension {
185 * uint16_t num;
186 * uint16_t len;
187 * uint8_t payload[len];
188 * }
189 */
190
191 /* 38 bytes is the shortest possible ServerHello with a zero-length
192 * session_id and no extensions. */
193 if (previous_server_hello->len < 38) {
194 PORT_SetError(SEC_ERROR_INPUT_LEN);
195 return PR_FALSE;
196 }
197
198 /* First we need to figure out the length of the predicted ServerHello. Any
199 * session id in |previous_server_hello| needs to be removed
200 * (or replaced). */
201 old_session_id_length = previous_server_hello->data[34];
202
203 extensions.len = 0;
204
205 if (previous_server_hello->len >= 35 + old_session_id_length + 3 + 2) {
206 /* Extensions present */
207 unsigned int offset = 35 + old_session_id_length + 3;
208 extensions.data = previous_server_hello->data + offset;
209 extensions.len = previous_server_hello->len - offset;
210 }
211
212 /* Sum the lengths of all the extensions that we wish to include */
213 extensions_len = 0;
214 if (!ssl3_ForEachExtension(&extensions, is_resuming, ssl3_AccumlateLengths,
215 &extensions_len)) {
216 return PR_FALSE;
217 }
218
219 old_extensions_len =
220 (previous_server_hello->len - 35 - old_session_id_length - 3 - 2);
221
222 session_id_len = 0;
223 if (ss->sec.ci.sid)
224 session_id_len = ss->sec.ci.sid->u.ssl3.sessionIDLength;
225 server_hello_len = previous_server_hello->len +
226 session_id_len - old_session_id_length +
227 extensions_len - old_extensions_len;
228
229 header[0] = server_hello;
230 PutBE24(header + 1, server_hello_len);
231 hashUpdate(header, 4, ctx);
232
233 hashUpdate(previous_server_hello->data, 34, ctx);
234 hashUpdate(&session_id_len, sizeof(session_id_len), ctx);
235 if (session_id_len)
236 hashUpdate(ss->sec.ci.sid->u.ssl3.sessionID, session_id_len, ctx);
237 hashUpdate(previous_server_hello->data + 35 + old_session_id_length, 3,
238 ctx);
239
240 if (extensions.len) {
241 PutBE16(header, extensions_len);
242 hashUpdate(header, 2, ctx);
243
244 if (!ssl3_ForEachExtension(&extensions, is_resuming, hashUpdate, ctx))
245 return PR_FALSE;
246 }
247
248 if (!is_resuming) {
249 unsigned int certificate_message_len = 3, i;
250 for (i = 0; ss->ssl3.predictedCertChain[i]; i++) {
251 certificate_message_len += 3;
252 certificate_message_len +=
253 ss->ssl3.predictedCertChain[i]->derCert.len;
254 }
255
256 header[0] = certificate;
257 PutBE24(header + 1, certificate_message_len);
258 hashUpdate(header, 4, ctx);
259
260 PutBE24(header, certificate_message_len - 3);
261 hashUpdate(header, 3, ctx);
262
263 for (i = 0; ss->ssl3.predictedCertChain[i]; i++) {
264 unsigned int len = ss->ssl3.predictedCertChain[i]->derCert.len;
265 PutBE24(header, len);
266 hashUpdate(header, 3, ctx);
267 hashUpdate(ss->ssl3.predictedCertChain[i]->derCert.data, len, ctx);
268 }
269
270 header[0] = server_hello_done;
271 header[1] = header[2] = header[3] = 0;
272 hashUpdate(header, 4, ctx);
273 }
274
275 return PR_TRUE;
276 }
277
278 /* ssl3_SnapStartHash is called with the contents of the server's predicted
279 * response and updates both the Finished hash and an FNV641a hash. */
280 static void
281 ssl3_SnapStartHash(const unsigned char *data, unsigned int len, void *ctx)
282 {
283 SECStatus rv;
284 void **ptrs = (void **) ctx;
285 sslSocket *ss = ptrs[0];
286 PRUint64 *fnv = ptrs[1];
287
288 FNV1A64_Update(fnv, data, len);
289 rv = ssl3_UpdateHandshakeHashes(ss, (unsigned char *) data, len);
290 if (rv != SECSuccess)
291 PR_Assert("rv == SECSuccess", __FILE__, __LINE__);
292 }
293
294 static PRInt32
295 ssl3_SendEmptySnapStartXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
296 {
297 SECStatus rv;
298
299 if (maxBytes < 4)
300 return 0;
301
302 if (append) {
303 rv = ssl3_AppendHandshakeNumber(ss, ssl_snap_start_xtn, 2);
304 if (rv != SECSuccess)
305 return -1;
306 rv = ssl3_AppendHandshakeNumber(ss, 0 /* empty extension */, 2);
307 if (rv != SECSuccess)
308 return -1;
309 if (!ss->sec.isServer) {
310 TLSExtensionData *xtnData = &ss->xtnData;
311 xtnData->advertised[xtnData->numAdvertised++] = ssl_snap_start_xtn;
312 }
313 }
314 return 4;
315 }
316
317 static SECStatus
318 ssl3_BufferEnsure(sslBuffer *buf, unsigned int extra_bytes)
319 {
320 if (buf->space < buf->len + extra_bytes)
321 return sslBuffer_Grow(buf, buf->len + extra_bytes);
322 return SECSuccess;
323 }
324
325 /* ssl3_AppendSnapStartRecordHeader appends a 5 byte TLS record header to the
326 * sendBuf of the given sslSocket. */
327 static SECStatus
328 ssl3_AppendSnapStartRecordHeader(sslSocket *ss, SSL3ContentType type,
329 unsigned int len)
330 {
331 SECStatus rv;
332
333 rv = ssl3_BufferEnsure(&ss->sec.ci.sendBuf, 5);
334 if (rv != SECSuccess)
335 return rv;
336 ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len + 0] = type;
337 PutBE16(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len + 1], ss->version);
338 PutBE16(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len + 3], len);
339 ss->sec.ci.sendBuf.len += 5;
340 return SECSuccess;
341 }
342
343 /* ssl3_AppendSnapStartHandshakeRecord appends a (possibly encrypted) record to
344 ** the sendBuf of the given sslSocket.
345 ** f: a function which will append the bytes of the record (not including the
346 ** 5 byte header) to the sendBuf.
347 */
348 static SECStatus
349 ssl3_AppendSnapStartHandshakeRecord(sslSocket *ss, SECStatus (*f) (sslSocket*),
350 PRBool encrypt)
351 {
352 SECStatus rv;
353 unsigned int record_offset, record_len;
354
355 /* ssl3_CompressMACEncryptRecord will deal with the record header if we are
356 * encrypting. */
357 if (!encrypt) {
358 /* The zero length argument here is a dummy value. We write the real
359 * length once we know it, below. */
360 rv = ssl3_AppendSnapStartRecordHeader(ss, content_handshake, 0);
361 if (rv != SECSuccess)
362 return rv;
363 }
364
365 record_offset = ss->sec.ci.sendBuf.len;
366 rv = f(ss);
367 if (rv != SECSuccess)
368 return rv;
369 record_len = ss->sec.ci.sendBuf.len - record_offset;
370 if (!encrypt) {
371 PutBE16(&ss->sec.ci.sendBuf.buf[record_offset - 2], record_len);
372 } else {
373 /* ssl3_CompressMACEncryptRecord writes to |ss->sec.writeBuf|
374 * so we copy it back to |ss->sec.ci.sendBuf| */
375 /* TODO(agl): the buffer copy here is a bodge. See TODO at the top of
376 * the file. */
377 rv = ssl3_CompressMACEncryptRecord(
378 ss, content_handshake,
379 &ss->sec.ci.sendBuf.buf[record_offset], record_len);
380 if (rv != SECSuccess)
381 return rv;
382 ss->sec.ci.sendBuf.len -= record_len;
383 ssl3_BufferEnsure(&ss->sec.ci.sendBuf, ss->sec.writeBuf.len);
384 memcpy(&ss->sec.ci.sendBuf.buf[record_offset], ss->sec.writeBuf.buf,
385 ss->sec.writeBuf.len);
386 ss->sec.ci.sendBuf.len += ss->sec.writeBuf.len;
387 ss->sec.writeBuf.len = 0;
388 }
389
390 return SECSuccess;
391 }
392
393 /* ssl3_AppendSnapStartApplicationData appends an encrypted Application Data
394 ** record the sendBuf of the given sslSocket.
395 */
396 static SECStatus ssl3_AppendSnapStartApplicationData(
397 sslSocket *ss, const SSL3Opaque *data, unsigned int len)
398 {
399 SECStatus rv;
400
401 /* TODO(agl): the buffer copy here is a bodge. See TODO at the top of the
402 * file. */
403 rv = ssl3_CompressMACEncryptRecord(ss, content_application_data, data, len);
404 if (rv != SECSuccess)
405 return rv;
406 rv = ssl3_BufferEnsure(&ss->sec.ci.sendBuf, ss->sec.writeBuf.len);
407 if (rv != SECSuccess)
408 return rv;
409 memcpy(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len],
410 ss->sec.writeBuf.buf, ss->sec.writeBuf.len);
411 ss->sec.ci.sendBuf.len += ss->sec.writeBuf.len;
412 ss->sec.writeBuf.len = 0;
413
414 return SECSuccess;
415 }
416
417 static SECStatus ssl3_SendSnapStartFinished(sslSocket *ss)
418 {
419 /* We use ssl_SEND_FLAG_NO_FLUSH here because this finished message is
420 * going to end up in the middle of the Snap Start extension. So
421 * transmitting |sendBuf| at this point would result in an incomplete
422 * ClientHello. */
423 return ssl3_SendFinished(ss, ssl_SEND_FLAG_NO_FLUSH);
424 }
425
426 /* ssl3_FindOrbit is called for each extension in a ServerHello message. It
427 ** tests for a Snap Start extension and records the server's orbit when found.
428 ** data: the extension data (including the four type and length bytes)
429 ** length: the length, in bytes, of |data|
430 ** ptr: a pointer to a uint8_t[9]. The orbit, if found, is copied into the
431 ** first 8 bytes and then the ninth byte is set to one.
432 */
433 static void
434 ssl3_FindOrbit(const unsigned char *data, unsigned int length, void *ptr)
435 {
436 unsigned char *orbit = (unsigned char *) ptr;
437
438 unsigned int extension_num = GetBE16(data);
439 if (extension_num == ssl_snap_start_xtn &&
440 length == 4 + 8 /* orbit */ + 2 /* snap start cipher suite */) {
441 memcpy(orbit, data + 4, 8);
442 /* A last byte of 1 indicates that the previous eight are valid. */
443 orbit[8] = 1;
444 }
445 }
446
447 /* ssl3_CanSnapStart returns true if we are able to perform Snap Start on
448 ** the given socket.
449 ** extensions: on successful return, this is filled in with the contents of
450 ** the server's predicted extensions. This points within
451 ** |ss->ssl3.serverHelloPredictionData|.
452 ** resuming: PR_TRUE iff we wish to attempt a Snap Start resume
453 ** out_orbit: if this function returns PR_TRUE, then |out_orbit| is filled
454 ** with the server's predicted orbit value.
455 ** The |hs.cipher_suite|, |hs.cipher_def| and |hs.compression| fields of |ss|
456 ** are set to match the predicted ServerHello on successful exit (and may still
457 ** be modified on failure).
458 */
459 static PRBool
460 ssl3_CanSnapStart(sslSocket *ss, SECItem *extensions, PRBool resuming,
461 unsigned char out_orbit[8]) {
462 const unsigned char *server_hello;
463 unsigned int server_hello_len, session_id_len, cipher_suite_offset;
464 unsigned int extensions_offset, cipher_suite, compression_method;
465 unsigned char orbit[9];
466 SECStatus rv;
467 SSL3ProtocolVersion version;
468
469 /* If we don't have the information needed then we can't perform a Snap
470 * Start. */
471 if (!ss->ssl3.predictedCertChain || !ss->ssl3.serverHelloPredictionData.data )
472 return PR_FALSE;
473
474 /* When the sizes of the fields in the ClientHello are calculated, they'll
475 * take the length of the Snap Start extension to be zero, so currently
476 * it's as if this extension didn't exist, which is the state that we
477 * need. */
478
479 server_hello = ss->ssl3.serverHelloPredictionData.data;
480 server_hello_len = ss->ssl3.serverHelloPredictionData.len;
481
482 if (server_hello_len < 2 + 32 + 1)
483 return PR_FALSE;
484 session_id_len = server_hello[2 + 32];
485 cipher_suite_offset = 2 + 32 + 1 + session_id_len;
486 if (server_hello_len < cipher_suite_offset + 3)
487 return PR_FALSE;
488 extensions_offset = cipher_suite_offset + 3;
489
490 version = (SSL3ProtocolVersion) GetBE16(server_hello);
491 if (MSB(version) < MSB(SSL_LIBRARY_VERSION_3_0))
492 return PR_FALSE;
493 rv = ssl3_NegotiateVersion(ss, version);
494 if (rv != SECSuccess)
495 return PR_FALSE;
496
497 cipher_suite = GetBE16(&server_hello[cipher_suite_offset]);
498 ss->ssl3.hs.cipher_suite = (ssl3CipherSuite)cipher_suite;
499 ss->ssl3.hs.suite_def = ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite);
500 if (!ss->ssl3.hs.suite_def)
501 return PR_FALSE;
502 compression_method = server_hello[cipher_suite_offset + 2];
503 if (compression_method != ssl_compression_null) {
504 /* TODO(agl): support compression. */
505 return PR_FALSE;
506 }
507 ss->ssl3.hs.compression = ssl_compression_null;
508
509 extensions->data = (unsigned char *) server_hello + extensions_offset;
510 extensions->len = server_hello_len - extensions_offset;
511
512 /* The last byte is used to indictate that the previous eight are valid. */
513 orbit[8] = 0;
514 if (!ssl3_ForEachExtension(extensions, resuming, ssl3_FindOrbit, orbit))
515 return PR_FALSE;
516
517 if (!orbit[8])
518 return PR_FALSE;
519
520 memcpy(out_orbit, orbit, 8);
521
522 return PR_TRUE;
523 }
524
525 /* ssl3_UpdateClientHelloLengths rewrites the handshake header length and
526 ** extensions length in the ClientHello to reflect the addition of the Snap
527 ** Start extension.
528 ** snap_start_extension_len_offset: the number of bytes of the ClientHello to
529 ** skip in order to find the embedded length of the Snap Start extension.
530 */
531 static void
532 ssl3_UpdateClientHelloLengths(sslSocket *ss,
533 unsigned int snap_start_extension_len_offset,
534 sslSessionID *sid) {
535 unsigned int extension_length, old_length, new_length, new_session_id_len;
536 unsigned int offset, ciphers_length, compressions_len;
537
538 extension_length =
539 ss->sec.ci.sendBuf.len - snap_start_extension_len_offset - 2;
540 PutBE16(&ss->sec.ci.sendBuf.buf[snap_start_extension_len_offset],
541 extension_length);
542
543 /* The length in the handshake header is short by extension_length + 4
544 * bytes. */
545 old_length = GetBE24(&ss->sec.ci.sendBuf.buf[1]);
546 new_length = old_length + extension_length + 4;
547 PutBE24(&ss->sec.ci.sendBuf.buf[1], new_length);
548
549 /* The length of the extensions block is similarly wrong. */
550 new_session_id_len = 0;
551 if (sid)
552 new_session_id_len = sid->u.ssl3.sessionIDLength;
553 offset = 4 + 2 + 32 + 1 + new_session_id_len;
554 ciphers_length = GetBE16(&ss->sec.ci.sendBuf.buf[offset]);
555 offset += 2 + ciphers_length;
556 compressions_len = ss->sec.ci.sendBuf.buf[offset];
557 offset += 1 + compressions_len;
558 old_length = GetBE16(&ss->sec.ci.sendBuf.buf[offset]);
559 new_length = old_length + extension_length + 4;
560 PutBE16(&ss->sec.ci.sendBuf.buf[offset], new_length);
561 }
562
563 /* ssl3_FindServerNPNExtension is a callback function for ssl3_ForEachExtension.
564 * It looks for a Next Protocol Negotiation and saves the payload of the
565 * extension in the given SECItem */
566 static void
567 ssl3_FindServerNPNExtension(const unsigned char* data, unsigned int length,
568 void *ctx)
569 {
570 SECItem *server_npn_extension = (SECItem*) ctx;
571
572 unsigned int extension_num = GetBE16(data);
573 if (extension_num == ssl_next_proto_neg_xtn && length >= 4) {
574 server_npn_extension->data = (unsigned char*)data + 4;
575 server_npn_extension->len = length - 4;
576 }
577 }
578
579 /* ssl3_MaybeWriteNextProtocol deals with the interaction of Next Protocol
580 * Negotiation and Snap Start. It's called just before we serialise the embedded
581 * Finished message in the extension. At this point, if NPN is enabled, we have
582 * to include a NextProtocol message. */
583 static SECStatus
584 ssl3_MaybeWriteNextProtocol(sslSocket *ss, SECItem *server_hello_extensions)
585 {
586 PRUint16 i16;
587 SECItem server_npn_extension;
588
589 for (i16 = 0; i16 < ss->xtnData.numAdvertised; i16++) {
590 if (ss->xtnData.advertised[i16] == ssl_next_proto_neg_xtn)
591 break;
592 }
593
594 if (i16 == ss->xtnData.numAdvertised) {
595 /* We didn't send an NPN extension, so no need to do anything here. */
596 return SECSuccess;
597 }
598
599 memset(&server_npn_extension, 0, sizeof(server_npn_extension));
600
601 ssl3_ForEachExtension(
602 server_hello_extensions, PR_FALSE /* is_resuming: value doesn't matter
603 in this case */, ssl3_FindServerNPNExtension, &server_npn_extension);
604
605 if (server_npn_extension.data == NULL) {
606 /* We predicted that the server doesn't support NPN, so nothing to do
607 * here. */
608 return SECSuccess;
609 }
610
611 ssl3_ClientHandleNextProtoNegoXtn(ss, ssl_next_proto_neg_xtn,
612 &server_npn_extension);
613
614 if (ss->ssl3.nextProtoState == SSL_NEXT_PROTO_NO_SUPPORT) {
615 /* The server's predicted NPN extension was malformed. We're didn't pick
616 * a protocol so we won't send a NextProtocol message. However, this is
617 * probably fatal to the connection. */
618 return SECSuccess;
619 }
620
621 return ssl3_AppendSnapStartHandshakeRecord(ss, ssl3_SendNextProto,
622 PR_TRUE /* encrypt */);
623 }
624
625 /* ssl3_SendSnapStartXtn appends a Snap Start extension. It assumes that the
626 * inchoate ClientHello is in |ss->sec.ci.sendBuf|. */
627 PRInt32
628 ssl3_SendSnapStartXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes)
629 {
630 unsigned char orbit[8];
631 PRBool resuming = PR_FALSE;
632 unsigned char suggested_server_random[32];
633 SECStatus rv;
634 PRUint64 fnv;
635 /* The context for |ssl3_SnapStartHash|. The first pointer points to |ss|
636 * and the second to the running FNV1A64 hash of the predicted server
637 * response. */
638 void *ctx[2];
639 unsigned int snap_start_extension_len_offset, original_sendbuf_len;
640 ssl3CipherSpec *temp;
641 sslSessionID *sid;
642 SECItem server_extensions;
643
644 if (!ss->opt.enableSnapStart)
645 return 0;
646
647 original_sendbuf_len = ss->sec.ci.sendBuf.len;
648
649 /* This function is called twice for each ClientHello emitted. The first
650 * time around is to calculate the sizes of the extension (|append| is
651 * false). The second time around is to actually write out the bytes
652 * (|append| is true).
653 *
654 * We always return 0 bytes in each case because we want to be able to hash
655 * the inchoate ClientHello as if this extension was missing: that's why
656 * it's important that this always be the last extension serialised. */
657 sid = ss->sec.ci.sid;
658
659 if (!ss->opt.enableSessionTickets || ss->sec.isServer)
660 return 0;
661
662 /* If we are sending a SessionTicket then the first time around
663 * ticketTimestampVerified will be true but it's reset after serialising
664 * the session ticket extension, so we have
665 * |clientSentNonEmptySessionTicket|. */
666 if (ss->xtnData.clientSentNonEmptySessionTicket) {
667 resuming = PR_TRUE;
668 } else if (sid->u.ssl3.sessionTicket.ticket.data &&
669 ss->xtnData.ticketTimestampVerified) {
670 resuming = PR_TRUE;
671 }
672
673 if (!ssl3_CanSnapStart(ss, &server_extensions, resuming, orbit))
674 return ssl3_SendEmptySnapStartXtn(ss, append, maxBytes);
675
676 /* At this point we are happy that we are going to send a non-empty Snap
677 * Start extension. If we are still calculating length then we lie and
678 * return 0 so that everything is set up as if the extension didn't exist
679 * when this function is called again later. */
680
681 if (!append)
682 return 0;
683
684 /* |ss->sec.ci.sendBuf.buf| contains the inchoate ClientHello. This copies
685 * the ClientHello's gmt_unix_time into the suggested server random. */
686 memcpy(suggested_server_random, ss->sec.ci.sendBuf.buf + 6, 4);
687 memcpy(suggested_server_random + 4, orbit, 8);
688 rv = PK11_GenerateRandom(suggested_server_random + 12, 20);
689 if (rv != SECSuccess)
690 goto loser;
691 memcpy(ss->ssl3.serverHelloPredictionData.data + 2, suggested_server_random,
692 32);
693
694 memcpy(&ss->ssl3.hs.server_random, suggested_server_random, 32);
695
696 PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
697 rv = ssl3_SetupPendingCipherSpec(ss);
698 if (rv != SECSuccess)
699 goto loser;
700 ss->ssl3.hs.isResuming = resuming;
701
702 FNV1A64_Init(&fnv);
703 ctx[0] = ss;
704 ctx[1] = &fnv;
705
706 if (!ssl3_PredictServerResponse(ss, &ss->ssl3.serverHelloPredictionData,
707 resuming, ssl3_SnapStartHash, ctx)) {
708 /* It's not a fatal error if the predicted ServerHello was invalid. */
709 return 0;
710 }
711 FNV1A64_Final(&fnv);
712
713 /* Now we grow the send buffer to accomodate the extension type and length,
714 * orbit, suggested random and predicted server response hash without
715 * calling ssl3_AppendHandshake (which would also update the Finished
716 * hash). */
717 if (ssl3_BufferEnsure(&ss->sec.ci.sendBuf, 4 + 8 + 20 + 8) != SECSuccess)
718 goto loser;
719
720 PutBE16(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len],
721 ssl_snap_start_xtn);
722 ss->sec.ci.sendBuf.len += 2;
723 /* Skip over the length for now. */
724 snap_start_extension_len_offset = ss->sec.ci.sendBuf.len;
725 ss->sec.ci.sendBuf.len += 2;
726 memcpy(ss->sec.ci.sendBuf.buf + ss->sec.ci.sendBuf.len, orbit, 8);
727 ss->sec.ci.sendBuf.len += 8;
728 memcpy(&ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len],
729 suggested_server_random + 12, 20);
730 ss->sec.ci.sendBuf.len += 20;
731 memcpy(ss->sec.ci.sendBuf.buf + ss->sec.ci.sendBuf.len, &fnv, 8);
732 ss->sec.ci.sendBuf.len += 8;
733
734 if (!resuming) {
735 /* Write ClientKeyExchange */
736 ss->sec.peerCert =
737 CERT_DupCertificate(ss->ssl3.predictedCertChain[0]);
738 rv = ssl3_AppendSnapStartHandshakeRecord(
739 ss, ssl3_SendClientKeyExchange, PR_FALSE /* do not encrypt */);
740 if (rv != SECSuccess)
741 goto loser;
742 } else {
743 SSL3Finished hashes;
744 TLSFinished tlsFinished;
745 unsigned char hdr[4];
746
747 rv = ssl3_SetupMasterSecretFromSessionID(ss);
748 if (rv == SECFailure)
749 goto loser;
750
751 if (sid->peerCert != NULL) {
752 ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
753 ssl3_CopyPeerCertsFromSID(ss, sid);
754 }
755
756 rv = ssl3_InitPendingCipherSpec(ss, NULL /* re-use master secret */);
757 if (rv != SECSuccess)
758 goto loser;
759
760 /* Need to add the server's predicted Finished message to our handshake
761 * hash in order to be able to produce our own Finished message. */
762 rv = ssl3_ComputeHandshakeHashes(ss, ss->ssl3.pwSpec, &hashes,
763 0 /* only for SSL3 */);
764 if (rv != SECSuccess)
765 goto loser;
766
767 rv = ssl3_ComputeTLSFinished(ss->ssl3.pwSpec, PR_TRUE /* isServer */,
768 &hashes, &tlsFinished);
769 if (rv != SECSuccess)
770 goto loser;
771
772 hdr[0] = (unsigned char) finished;
773 hdr[1] = hdr[2] = 0;
774 hdr[3] = sizeof(tlsFinished.verify_data);
775 ssl3_UpdateHandshakeHashes(ss, hdr, sizeof(hdr));
776 ssl3_UpdateHandshakeHashes(ss, tlsFinished.verify_data,
777 sizeof(tlsFinished.verify_data));
778
779 /* Store the Finished message so that we can verify it later */
780 memcpy(&ss->ssl3.hs.finishedMsgs.tFinished[1], tlsFinished.verify_data,
781 sizeof(tlsFinished.verify_data));
782 }
783
784 /* Write ChangeCipherSpec */
785 rv = ssl3_AppendSnapStartRecordHeader(ss, content_change_cipher_spec, 1);
786 if (rv != SECSuccess)
787 goto loser;
788 rv = ssl3_BufferEnsure(&ss->sec.ci.sendBuf, 1);
789 if (rv != SECSuccess)
790 goto loser;
791 ss->sec.ci.sendBuf.buf[ss->sec.ci.sendBuf.len] = change_cipher_spec_choice;
792 ss->sec.ci.sendBuf.len++;
793
794 /* We swap |cwSpec| and |pwSpec| temporarily in order to encrypt some
795 * records before switching them back so that the whole ClientHello doesn't
796 * get encrypted. */
797 ssl_GetSpecWriteLock(ss);
798 temp = ss->ssl3.cwSpec;
799 ss->ssl3.cwSpec = ss->ssl3.pwSpec;
800 ss->ssl3.pwSpec = temp;
801 ss->ssl3.cwSpec->write_seq_num.high = 0;
802 ss->ssl3.cwSpec->write_seq_num.low = 0;
803 ssl_ReleaseSpecWriteLock(ss);
804
805 rv = ssl3_MaybeWriteNextProtocol(ss, &server_extensions);
806 if (rv != SECSuccess)
807 goto loser;
808
809 /* Write Finished */
810 rv = ssl3_AppendSnapStartHandshakeRecord(ss, ssl3_SendSnapStartFinished,
811 PR_TRUE /* encrypt */);
812 if (rv != SECSuccess)
813 goto loser;
814
815 /* Write application data */
816 if (ss->ssl3.snapStartApplicationData.data) {
817 rv = ssl3_AppendSnapStartApplicationData(
818 ss, ss->ssl3.snapStartApplicationData.data,
819 ss->ssl3.snapStartApplicationData.len);
820 SECITEM_FreeItem(&ss->ssl3.snapStartApplicationData, PR_FALSE);
821 if (rv != SECSuccess)
822 goto loser;
823 }
824
825 /* Revert the write cipher spec because the ClientHello will get encrypted
826 * with it otherwise. */
827 ssl_GetSpecWriteLock(ss);
828 temp = ss->ssl3.cwSpec;
829 ss->ssl3.cwSpec = ss->ssl3.pwSpec;
830 ss->ssl3.pwSpec = temp;
831 ssl_ReleaseSpecWriteLock(ss);
832
833 /* Update the lengths in the ClientHello to reflect this extension. */
834 ssl3_UpdateClientHelloLengths(ss, snap_start_extension_len_offset, sid);
835
836 /* Keep a copy of the ClientHello around so that we can hash it in the case
837 * the the Snap Start handshake is rejected. */
838
839 if (SECITEM_AllocItem(NULL, &ss->ssl3.hs.origClientHello,
840 ss->sec.ci.sendBuf.len) == NULL) {
841 goto loser;
842 }
843 memcpy(ss->ssl3.hs.origClientHello.data, ss->sec.ci.sendBuf.buf,
844 ss->sec.ci.sendBuf.len);
845 ss->ssl3.hs.origClientHello.len = ss->sec.ci.sendBuf.len;
846
847 ss->xtnData.advertised[ss->xtnData.numAdvertised++] = ssl_snap_start_xtn;
848
849 if (resuming) {
850 ss->ssl3.hs.snapStartType = snap_start_resume;
851 } else {
852 ss->ssl3.hs.snapStartType = snap_start_full;
853 }
854
855 return 0;
856
857 loser:
858 /* In the case of an error we revert the length of the sendBuf to remove
859 * any partial data that we may have appended. */
860 ss->sec.ci.sendBuf.len = original_sendbuf_len;
861 return -1;
862 }
863
864 SECStatus ssl3_ClientHandleSnapStartXtn(sslSocket *ss, PRUint16 ex_type,
865 SECItem *data) {
866 /* The work of saving the ServerHello is done in ssl3_HandleServerHello,
867 * where its contents are available. Here we renognise that the saved
868 * ServerHello message contains a Snap Start extension and mark it as
869 * valid. */
870 ss->ssl3.serverHelloPredictionDataValid = PR_TRUE;
871 return SECSuccess;
872 }
873
874 SECStatus
875 SSL_SetPredictedPeerCertificates(PRFileDesc *fd, CERTCertificate **certs,
876 unsigned int numCerts)
877 {
878 sslSocket *ss;
879 unsigned int i;
880
881 ss = ssl_FindSocket(fd);
882 if (!ss) {
883 SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetPredictedPeerCertificates",
884 SSL_GETPID(), fd));
885 return SECFailure;
886 }
887
888 ss->ssl3.predictedCertChain =
889 PORT_NewArray(CERTCertificate*, numCerts + 1);
890 if (!ss->ssl3.predictedCertChain)
891 return SECFailure; /* error code was set */
892 for (i = 0; i < numCerts; i++)
893 ss->ssl3.predictedCertChain[i] = CERT_DupCertificate(certs[i]);
894 ss->ssl3.predictedCertChain[numCerts] = NULL;
895
896 return SECSuccess;
897 }
898
899 void
900 ssl3_CleanupPredictedPeerCertificates(sslSocket *ss) {
901 unsigned int i;
902
903 if (!ss->ssl3.predictedCertChain)
904 return;
905
906 for (i = 0; ss->ssl3.predictedCertChain[i]; i++) {
907 CERT_DestroyCertificate(ss->ssl3.predictedCertChain[i]);
908 }
909
910 PORT_Free(ss->ssl3.predictedCertChain);
911 ss->ssl3.predictedCertChain = NULL;
912 }
913
914 SECStatus
915 SSL_GetPredictedServerHelloData(PRFileDesc *fd, const unsigned char **data,
916 unsigned int *data_len)
917 {
918 sslSocket *ss;
919
920 ss = ssl_FindSocket(fd);
921 if (!ss) {
922 SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetPredictedServerHelloData",
923 SSL_GETPID(), fd));
924 *data = NULL;
925 *data_len = 0;
926 return SECFailure;
927 }
928
929 if (!ss->ssl3.serverHelloPredictionDataValid) {
930 *data = NULL;
931 *data_len = 0;
932 } else {
933 *data = ss->ssl3.serverHelloPredictionData.data;
934 *data_len = ss->ssl3.serverHelloPredictionData.len;
935 }
936 return SECSuccess;
937 }
938
939 SECStatus
940 SSL_SetPredictedServerHelloData(PRFileDesc *fd, const unsigned char *data,
941 unsigned int data_len)
942 {
943 sslSocket *ss;
944
945 ss = ssl_FindSocket(fd);
946 if (!ss) {
947 SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetPredictedServerHelloData",
948 SSL_GETPID(), fd));
949 return SECFailure;
950 }
951
952 if (ss->ssl3.serverHelloPredictionData.data)
953 SECITEM_FreeItem(&ss->ssl3.serverHelloPredictionData, PR_FALSE);
954 if (!SECITEM_AllocItem(NULL, &ss->ssl3.serverHelloPredictionData, data_len))
955 return SECFailure;
956 memcpy(ss->ssl3.serverHelloPredictionData.data, data, data_len);
957 return SECSuccess;
958 }
959
960 SECStatus
961 SSL_SetSnapStartApplicationData(PRFileDesc *fd, const unsigned char *data,
962 unsigned int data_len)
963 {
964 sslSocket *ss;
965
966 ss = ssl_FindSocket(fd);
967 if (!ss) {
968 SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetSnapStartApplicationData",
969 SSL_GETPID(), fd));
970 return SECFailure;
971 }
972
973 if (ss->ssl3.snapStartApplicationData.data)
974 SECITEM_FreeItem(&ss->ssl3.snapStartApplicationData, PR_FALSE);
975 if (!SECITEM_AllocItem(NULL, &ss->ssl3.snapStartApplicationData, data_len))
976 return SECFailure;
977 memcpy(ss->ssl3.snapStartApplicationData.data, data, data_len);
978 return SECSuccess;
979 }
980
981 SECStatus
982 SSL_GetSnapStartResult(PRFileDesc *fd, SSLSnapStartResult *result)
983 {
984 sslSocket *ss;
985
986 ss = ssl_FindSocket(fd);
987 if (!ss) {
988 SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetSnapStartResult",
989 SSL_GETPID(), fd));
990 return SECFailure;
991 }
992
993 switch (ss->ssl3.hs.snapStartType) {
994 case snap_start_full:
995 *result = SSL_SNAP_START_FULL;
996 break;
997 case snap_start_recovery:
998 *result = SSL_SNAP_START_RECOVERY;
999 break;
1000 case snap_start_resume:
1001 *result = SSL_SNAP_START_RESUME;
1002 break;
1003 case snap_start_resume_recovery:
1004 *result = SSL_SNAP_START_RESUME_RECOVERY;
1005 break;
1006 default:
1007 PORT_Assert(ss->ssl3.hs.snapStartType == snap_start_none);
1008 *result = SSL_SNAP_START_NONE;
1009 break;
1010 }
1011
1012 return SECSuccess;
1013 }
1014
1015 /* Called form ssl3_HandleServerHello in the case that we sent a Snap Start
1016 ** ClientHello but received a ServerHello in reply.
1017 */
1018 SECStatus
1019 ssl3_ResetForSnapStartRecovery(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
1020 {
1021 SECStatus rv;
1022 PRUint8 hdr[4];
1023
1024 ss->ssl3.hs.ws = wait_server_hello;
1025
1026 /* Need to reset the Finished hashes to include the full ClientHello
1027 * message. */
1028
1029 rv = ssl3_RestartHandshakeHashes(ss);
1030 if (rv != SECSuccess)
1031 return rv;
1032 rv = ssl3_UpdateHandshakeHashes(ss, ss->ssl3.hs.origClientHello.data,
1033 ss->ssl3.hs.origClientHello.len);
1034 SECITEM_FreeItem(&ss->ssl3.hs.origClientHello, PR_FALSE);
1035 if (rv != SECSuccess)
1036 return rv;
1037
1038 hdr[0] = (PRUint8)server_hello;
1039 hdr[1] = (PRUint8)(length >> 16);
1040 hdr[2] = (PRUint8)(length >> 8);
1041 hdr[3] = (PRUint8)(length );
1042
1043 rv = ssl3_UpdateHandshakeHashes(ss, hdr, sizeof(hdr));
1044 if (rv != SECSuccess)
1045 return rv;
1046 rv = ssl3_UpdateHandshakeHashes(ss, b, length);
1047 if (rv != SECSuccess)
1048 return rv;
1049
1050 if (ss->ssl3.hs.snapStartType == snap_start_full) {
1051 ss->ssl3.hs.snapStartType = snap_start_recovery;
1052 } else {
1053 ss->ssl3.hs.snapStartType = snap_start_resume_recovery;
1054 }
1055
1056 ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NO_SUPPORT;
1057
1058 ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_TRUE/*freeSrvName*/);
1059
1060 return SECSuccess;
1061 }
OLDNEW
« no previous file with comments | « net/third_party/nss/ssl/fnv1a64.c ('k') | net/third_party/nss/ssl/ssl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698