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

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

Issue 9764001: Add DTLS support to NSS, contributed by Eric Rescorla. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Made changes suggested by rsleevi Created 8 years, 9 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
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 /*
2 * DTLS Protocol
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 * Eric Rescorla <ekr@rtfm.com>
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 /* $Id: $ */
41
42 #include "ssl.h"
43 #include "sslimpl.h"
44 #include "sslproto.h"
45
46 #ifndef PR_ARRAY_SIZE
47 #define PR_ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
48 #endif
49
50 static SECStatus dtls_TransmitMessageFlight(sslSocket *ss);
51 static void dtls_RetransmitTimerExpiredCb(sslSocket *ss);
52 static SECStatus dtls_SendSavedWriteData(sslSocket *ss);
53
54 /* -28 adjusts for the IP/UDP header */
55 static const PRUint16 COMMON_MTU_VALUES[] = {
56 1500 - 28, /* Ethernet MTU */
57 1280 - 28, /* IPv6 minimum MTU */
58 576 - 28, /* Common assumption */
59 256 - 28 /* We're in serious trouble now */
60 };
61
62 #define DTLS_COOKIE_BYTES 32
63
64 /* List copied from ssl3con.c:cipherSuites */
65 static const ssl3CipherSuite nonDTLSSuites[] = {
66 #ifdef NSS_ENABLE_ECC
67 TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
68 TLS_ECDHE_RSA_WITH_RC4_128_SHA,
69 #endif /* NSS_ENABLE_ECC */
70 TLS_DHE_DSS_WITH_RC4_128_SHA,
71 #ifdef NSS_ENABLE_ECC
72 TLS_ECDH_RSA_WITH_RC4_128_SHA,
73 TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
74 #endif /* NSS_ENABLE_ECC */
75 SSL_RSA_WITH_RC4_128_MD5,
76 SSL_RSA_WITH_RC4_128_SHA,
77 TLS_RSA_EXPORT1024_WITH_RC4_56_SHA,
78 SSL_RSA_EXPORT_WITH_RC4_40_MD5,
79 0 /* End of list marker */
80 };
81
82 /* Map back and forth between TLS and DTLS versions in wire format.
83 * Mapping table is:
84 *
85 * TLS DTLS
86 * 1.1 (0302) 1.0 (feff)
87 */
88 SSL3ProtocolVersion
89 dtls_TLSVersionToDTLSVersion(SSL3ProtocolVersion tlsv)
90 {
91 /* Anything other than TLS 1.1 is an error, so return
92 * the invalid version ffff. */
93 if (tlsv != SSL_LIBRARY_VERSION_TLS_1_1)
94 return 0xffff;
95
96 return SSL_LIBRARY_VERSION_DTLS_1_0_WIRE;
97 }
98
99 /* Map known DTLS versions to known TLS versions.
100 * - Invalid versions (< 1.0) return a version of 0
101 * - Versions > known return a version one higher than we know of
102 * to accomodate a theoretically newer version */
103 SSL3ProtocolVersion
104 dtls_DTLSVersionToTLSVersion(SSL3ProtocolVersion dtlsv)
105 {
106 if (MSB(dtlsv) == 0xff) {
107 return 0;
108 }
109
110 if (dtlsv == SSL_LIBRARY_VERSION_DTLS_1_0_WIRE)
111 return SSL_LIBRARY_VERSION_TLS_1_1;
112
113 /* Return a fictional higher version than we know of */
114 return SSL_LIBRARY_VERSION_TLS_1_1 + 1;
115 }
116
117 /* On this socket, Disable non-DTLS cipher suites in the argument's list */
118 SECStatus
119 ssl3_DisableNonDTLSSuites(sslSocket * ss)
120 {
121 const ssl3CipherSuite * suite;
122
123 for (suite = nonDTLSSuites; *suite; ++suite) {
124 SECStatus rv = ssl3_CipherPrefSet(ss, *suite, PR_FALSE);
125
126 PORT_Assert(rv == SECSuccess); /* else is coding error */
127 }
128 return SECSuccess;
129 }
130
131 /* Allocate a DTLSQueuedMessage.
132 *
133 * Called from dtls_QueueMessage()
134 */
135 static DTLSQueuedMessage *
136 dtls_AllocQueuedMessage(PRUint16 epoch, SSL3ContentType type,
137 const unsigned char *data, PRUint32 len)
138 {
139 DTLSQueuedMessage *msg = NULL;
140
141 msg = PORT_ZAlloc(sizeof(DTLSQueuedMessage));
142 if (!msg)
143 return NULL;
144
145 msg->data = PORT_Alloc(len);
146 if (!msg->data) {
147 PORT_Free(msg);
148 return NULL;
149 }
150 PORT_Memcpy(msg->data, data, len);
151
152 msg->len = len;
153 msg->epoch = epoch;
154 msg->type = type;
155
156 return msg;
157 }
158
159 /*
160 * Free a handshake message
161 *
162 * Called from dtls_FreeHandshakeMessages()
163 */
164 static void
165 dtls_FreeHandshakeMessage(DTLSQueuedMessage *msg)
166 {
167 if (!msg)
168 return;
169
170 PORT_ZFree(msg->data, msg->len);
171 PORT_Free(msg);
172 }
173
174 /*
175 * Free a list of handshake messages
176 *
177 * Called from:
178 * dtls_HandleHandshake()
179 * ssl3_DestroySSL3Info()
180 */
181 void
182 dtls_FreeHandshakeMessages(PRCList *list)
183 {
184 PRCList *cur_p;
185
186 while (!PR_CLIST_IS_EMPTY(list)) {
187 cur_p = PR_LIST_TAIL(list);
188 PR_REMOVE_LINK(cur_p);
189 dtls_FreeHandshakeMessage((DTLSQueuedMessage *)cur_p);
190 }
191 }
192
193 /* Called only from ssl3_HandleRecord, for each (deciphered) DTLS record.
194 * origBuf is the decrypted ssl record content and is expected to contain
195 * complete handshake records
196 * Caller must hold the handshake and RecvBuf locks.
197 *
198 * Note that this code uses msg_len for two purposes:
199 *
200 * (1) To pass the length to ssl3_HandleHandshakeMessage()
201 * (2) To carry the length of a message currently being reassembled
202 *
203 * However, unlike ssl3_HandleHandshake(), it is not used to carry
204 * the state of reassembly (i.e., whether one is in progress). That
205 * is carried in recvdHighWater and recvdFragments.
206 */
207 #define OFFSET_BYTE(o) (o/8)
208 #define OFFSET_MASK(o) (1 << (o%8))
209
210 SECStatus
211 dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
212 {
213 /* TODO(ekr@rtfm.com): OK for now.
214 * This doesn't work properly with asynchronous certificate validation.
215 * because that returns a WOULDBLOCK error. The current DTLS
216 * applications do not need asynchronous validation, but in the
217 * future we will need to add this.
218 */
219 sslBuffer buf = *origBuf;
220 SECStatus rv = SECSuccess;
221
222 PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
223 PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
224
225 while (buf.len > 0) {
226 PRUint8 type;
227 PRUint32 message_length;
228 PRUint16 message_seq;
229 PRUint32 fragment_offset;
230 PRUint32 fragment_length;
231 PRUint32 offset;
232
233 if (buf.len < 12) {
234 PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
235 rv = SECFailure;
236 break;
237 }
238
239 /* Parse the header */
240 type = buf.buf[0];
241 message_length = (buf.buf[1] << 16) | (buf.buf[2] << 8) | buf.buf[3];
242 message_seq = (buf.buf[4] << 8) | buf.buf[5];
243 fragment_offset = (buf.buf[6] << 16) | (buf.buf[7] << 8) | buf.buf[8];
244 fragment_length = (buf.buf[9] << 16) | (buf.buf[10] << 8) | buf.buf[11];
245
246 #define MAX_HANDSHAKE_MSG_LEN 0x1ffff /* 128k - 1 */
247 if (message_length > MAX_HANDSHAKE_MSG_LEN) {
248 (void)ssl3_DecodeError(ss);
249 PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
250 return SECFailure;
251 }
252 #undef MAX_HANDSHAKE_MSG_LEN
253
254 buf.buf += 12;
255 buf.len -= 12;
256
257 /* This fragment must be complete */
258 if (buf.len < fragment_length) {
259 PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
260 rv = SECFailure;
261 break;
262 }
263
264 /* Sanity check the packet contents */
265 if ((fragment_length + fragment_offset) > message_length) {
266 PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
267 rv = SECFailure;
268 break;
269 }
270
271 /* There are three ways we could not be ready for this packet.
272 *
273 * 1. It's a partial next message.
274 * 2. It's a partial or complete message beyond the next
275 * 3. It's a message we've already seen
276 *
277 * If it's the complete next message we accept it right away.
278 * This is the common case for short messages
279 */
280 if ((message_seq == ss->ssl3.hs.recvMessageSeq)
281 && (fragment_offset == 0)
282 && (fragment_length == message_length)) {
283 /* Complete next message. Process immediately */
284 ss->ssl3.hs.msg_type = (SSL3HandshakeType)type;
285 ss->ssl3.hs.msg_len = message_length;
286
287 /* At this point we are advancing our state machine, so
288 * we can free our last flight of messages */
289 dtls_FreeHandshakeMessages(ss->ssl3.hs.lastMessageFlight);
290 ss->ssl3.hs.recvdHighWater = -1;
291 dtls_CancelTimer(ss);
292
293 /* Reset the timer to the initial value if the retry counter
294 * is 0, per Sec. 4.2.4.1 */
295 if (ss->ssl3.hs.rtRetries == 0) {
296 ss->ssl3.hs.rtTimeoutMs = INITIAL_DTLS_TIMEOUT_MS;
297 }
298
299 rv = ssl3_HandleHandshakeMessage(ss, buf.buf, ss->ssl3.hs.msg_len);
300 if (rv == SECFailure) {
301 /* Do not attempt to process rest of messages in this record */
302 break;
303 }
304 } else {
305 if (message_seq < ss->ssl3.hs.recvMessageSeq) {
306 /* Case 3: we do an immediate retransmit if we're
307 * in a waiting state*/
308 if (ss->ssl3.hs.rtTimerCb == NULL) {
309 /* Ignore */
310 } else if (ss->ssl3.hs.rtTimerCb ==
311 dtls_RetransmitTimerExpiredCb) {
312 SSL_TRC(30, ("%d: SSL3[%d]: Retransmit detected",
313 SSL_GETPID(), ss->fd));
314 /* Check to see if we retransmitted recently. If so,
315 * suppress the triggered retransmit. This avoids
316 * retransmit wars after packet loss.
317 * This is not in RFC 5346 but should be
318 */
319 if ((PR_IntervalNow() - ss->ssl3.hs.rtTimerStarted) >
320 (ss->ssl3.hs.rtTimeoutMs / 4)) {
321 SSL_TRC(30,
322 ("%d: SSL3[%d]: Shortcutting retransmit timer",
323 SSL_GETPID(), ss->fd));
324
325 /* Cancel the timer and call the CB,
326 * which re-arms the timer */
327 dtls_CancelTimer(ss);
328 dtls_RetransmitTimerExpiredCb(ss);
329 rv = SECSuccess;
330 break;
331 } else {
332 SSL_TRC(30,
333 ("%d: SSL3[%d]: We just retransmitted. Ignoring.",
334 SSL_GETPID(), ss->fd));
335 rv = SECSuccess;
336 break;
337 }
338 } else if (ss->ssl3.hs.rtTimerCb == dtls_FinishedTimerCb) {
339 /* Retransmit the messages and re-arm the timer
340 * Note that we are not backing off the timer here.
341 * The spec isn't clear and my reasoning is that this
342 * may be a re-ordered packet rather than slowness,
343 * so let's be aggressive. */
344 dtls_CancelTimer(ss);
345 rv = dtls_TransmitMessageFlight(ss);
346 if (rv == SECSuccess) {
347 rv = dtls_StartTimer(ss, dtls_FinishedTimerCb);
348 }
349 if (rv != SECSuccess)
350 return rv;
351 break;
352 }
353 } else if (message_seq > ss->ssl3.hs.recvMessageSeq) {
354 /* Case 2
355 *
356 * Ignore this message. This means we don't handle out of
357 * order complete messages that well, but we're still
358 * compliant and this probably does not happen often
359 *
360 * TODO(ekr@rtfm.com): OK for now. Maybe do something smarter
361 * at some point?
362 */
363 } else {
364 /* Case 1
365 *
366 * Buffer the fragment for reassembly
367 */
368 /* Make room for the message */
369 if (ss->ssl3.hs.recvdHighWater == -1) {
370 PRUint32 map_length = OFFSET_BYTE(message_length) + 1;
371
372 rv = sslBuffer_Grow(&ss->ssl3.hs.msg_body, message_length);
373 if (rv != SECSuccess)
374 break;
375 /* Make room for the fragment map */
376 rv = sslBuffer_Grow(&ss->ssl3.hs.recvdFragments,
377 map_length);
378 if (rv != SECSuccess)
379 break;
380
381 /* Reset the reassembly map */
382 ss->ssl3.hs.recvdHighWater = 0;
383 PORT_Memset(ss->ssl3.hs.recvdFragments.buf, 0,
384 ss->ssl3.hs.recvdFragments.space);
385 ss->ssl3.hs.msg_type = (SSL3HandshakeType)type;
386 ss->ssl3.hs.msg_len = message_length;
387 }
388
389 /* If we have a message length mismatch, abandon the reassembly
390 * in progress and hope that the next retransmit will give us
391 * something sane
392 */
393 if (message_length != ss->ssl3.hs.msg_len) {
394 ss->ssl3.hs.recvdHighWater = -1;
395 PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
396 rv = SECFailure;
397 break;
398 }
399
400 /* Now copy this fragment into the buffer */
401 PORT_Assert((fragment_offset + fragment_length) <=
402 ss->ssl3.hs.msg_body.space);
403 PORT_Memcpy(ss->ssl3.hs.msg_body.buf + fragment_offset,
404 buf.buf, fragment_length);
405
406 /* This logic is a bit tricky. We have two values for
407 * reassembly state:
408 *
409 * - recvdHighWater contains the highest contiguous number of
410 * bytes received
411 * - recvdFragments contains a bitmask of packets received
412 * above recvdHighWater
413 *
414 * This avoids having to fill in the bitmask in the common
415 * case of adjacent fragments received in sequence
416 */
417 if (fragment_offset <= ss->ssl3.hs.recvdHighWater) {
418 /* Either this is the adjacent fragment or an overlapping
419 * fragment */
420 ss->ssl3.hs.recvdHighWater = fragment_offset +
421 fragment_length;
422 } else {
423 for (offset = fragment_offset;
424 offset < fragment_offset + fragment_length;
425 offset++) {
426 ss->ssl3.hs.recvdFragments.buf[OFFSET_BYTE(offset)] |=
427 OFFSET_MASK(offset);
428 }
429 }
430
431 /* Now figure out the new high water mark if appropriate */
432 for (offset = ss->ssl3.hs.recvdHighWater;
433 offset < ss->ssl3.hs.msg_len; offset++) {
434 /* Note that this loop is not efficient, since it counts
435 * bit by bit. If we have a lot of out-of-order packets,
436 * we should optimize this */
437 if (ss->ssl3.hs.recvdFragments.buf[OFFSET_BYTE(offset)] &
438 OFFSET_MASK(offset)) {
439 ss->ssl3.hs.recvdHighWater++;
440 } else {
441 break;
442 }
443 }
444
445 /* If we have all the bytes, then we are good to go */
446 if (ss->ssl3.hs.recvdHighWater == ss->ssl3.hs.msg_len) {
447 ss->ssl3.hs.recvdHighWater = -1;
448
449 rv = ssl3_HandleHandshakeMessage(ss,
450 ss->ssl3.hs.msg_body.buf,
451 ss->ssl3.hs.msg_len);
452 if (rv == SECFailure)
453 break; /* Skip rest of record */
454
455 /* At this point we are advancing our state machine, so
456 * we can free our last flight of messages */
457 dtls_FreeHandshakeMessages(ss->ssl3.hs.lastMessageFlight);
458 dtls_CancelTimer(ss);
459
460 /* If there have been no retries this time, reset the
461 * timer value to the default per Section 4.2.4.1 */
462 if (ss->ssl3.hs.rtRetries == 0) {
463 ss->ssl3.hs.rtTimeoutMs = INITIAL_DTLS_TIMEOUT_MS;
464 }
465 }
466 }
467 }
468
469 buf.buf += fragment_length;
470 buf.len -= fragment_length;
471 }
472
473 origBuf->len = 0; /* So ssl3_GatherAppDataRecord will keep looping. */
474
475 /* TODO(ekr@rtfm.com): OK for now. In future handle rv == SECWouldBlock
476 * safely in order to deal with asynchronous certificate verification */
477 return rv;
478 }
479
480 /* Enqueue a message (either handshake or CCS)
481 *
482 * Called from:
483 * dtls_StageHandshakeMessage()
484 * ssl3_SendChangeCipherSpecs()
485 */
486 SECStatus dtls_QueueMessage(sslSocket *ss, SSL3ContentType type,
487 const SSL3Opaque *pIn, PRInt32 nIn)
488 {
489 SECStatus rv = SECSuccess;
490 DTLSQueuedMessage *msg = NULL;
491
492 PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
493 PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
494
495 msg = dtls_AllocQueuedMessage(ss->ssl3.cwSpec->epoch, type, pIn, nIn);
496
497 if (!msg) {
498 PORT_SetError(SEC_ERROR_NO_MEMORY);
499 rv = SECFailure;
500 } else {
501 PR_APPEND_LINK(&msg->link, ss->ssl3.hs.lastMessageFlight);
502 }
503
504 return rv;
505 }
506
507 /* Add DTLS handshake message to the pending queue
508 * Empty the sendBuf buffer.
509 * This function returns SECSuccess or SECFailure, never SECWouldBlock.
510 * Always set sendBuf.len to 0, even when returning SECFailure.
511 *
512 * Called from:
513 * ssl3_AppendHandshakeHeader()
514 * dtls_FlushHandshake()
515 */
516 SECStatus
517 dtls_StageHandshakeMessage(sslSocket *ss)
518 {
519 SECStatus rv = SECSuccess;
520
521 PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
522 PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
523
524 /* This function is sometimes called when no data is actually to
525 * be staged, so just return SECSuccess. */
526 if (!ss->sec.ci.sendBuf.buf || !ss->sec.ci.sendBuf.len)
527 return rv;
528
529 rv = dtls_QueueMessage(ss, content_handshake,
530 ss->sec.ci.sendBuf.buf, ss->sec.ci.sendBuf.len);
531
532 /* Whether we succeeded or failed, toss the old handshake data. */
533 ss->sec.ci.sendBuf.len = 0;
534 return rv;
535 }
536
537 /* Enqueue the handshake message in sendBuf (if any) and then
538 * transmit the resulting flight of handshake messages.
539 *
540 * Called from:
541 * ssl3_FlushHandshake()
542 */
543 SECStatus
544 dtls_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags)
545 {
546 SECStatus rv = SECSuccess;
547
548 PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
549 PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
550
551 rv = dtls_StageHandshakeMessage(ss);
552 if (rv != SECSuccess)
553 return rv;
554
555 if (!(flags & ssl_SEND_FLAG_FORCE_INTO_BUFFER)) {
556 rv = dtls_TransmitMessageFlight(ss);
557 if (rv != SECSuccess)
558 return rv;
559
560 if (!(flags & ssl_SEND_FLAG_NO_RETRANSMIT)) {
561 ss->ssl3.hs.rtRetries = 0;
562 rv = dtls_StartTimer(ss, dtls_RetransmitTimerExpiredCb);
563 }
564 }
565
566 return rv;
567 }
568
569 /* The callback for when the retransmit timer expires
570 *
571 * Called from:
572 * dtls_CheckTimer()
573 * dtls_HandleHandshake()
574 */
575 static void
576 dtls_RetransmitTimerExpiredCb(sslSocket *ss)
577 {
578 SECStatus rv = SECFailure;
579
580 ss->ssl3.hs.rtRetries++;
581
582 if (!(ss->ssl3.hs.rtRetries % 3)) {
583 /* If one of the messages was potentially greater than > MTU,
584 * then downgrade. Do this every time we have retransmitted a
585 * message twice, per RFC 6347 Sec. 4.1.1 */
586 dtls_SetMTU(ss, ss->ssl3.hs.maxMessageSent - 1);
587 }
588
589 rv = dtls_TransmitMessageFlight(ss);
590 if (rv == SECSuccess) {
591
592 /* Re-arm the timer */
593 rv = dtls_RestartTimer(ss, PR_TRUE, dtls_RetransmitTimerExpiredCb);
594 }
595
596 if (rv == SECFailure) {
597 /* TODO(ekr@rtfm.com): OK for now. In future maybe signal the stack
598 * that we couldn't transmit. For now, let the read handle any real
599 * network errors */
600 }
601 }
602
603 /* Transmit a flight of handshake messages, stuffing them
604 * into as few records as seems reasonable
605 *
606 * Called from:
607 * dtls_FlushHandshake()
608 * dtls_RetransmitTimerExpiredCb()
609 */
610 static SECStatus
611 dtls_TransmitMessageFlight(sslSocket *ss)
612 {
613 SECStatus rv = SECSuccess;
614 PRCList *msg_p;
615 PRUint16 room_left = ss->ssl3.mtu;
616 PRInt32 sent;
617
618 ssl_GetXmitBufLock(ss);
619 ssl_GetSpecReadLock(ss);
620
621 /* DTLS does not buffer its handshake messages in
622 * ss->pendingBuf, but rather in the lastMessageFlight
623 * structure. This is just a sanity check that
624 * some programming error hasn't inadvertantly
625 * stuffed something in ss->pendingBuf
626 */
627 PORT_Assert(!ss->pendingBuf.len);
628 for (msg_p = PR_LIST_HEAD(ss->ssl3.hs.lastMessageFlight);
629 msg_p != ss->ssl3.hs.lastMessageFlight;
630 msg_p = PR_NEXT_LINK(msg_p)) {
631 DTLSQueuedMessage *msg = (DTLSQueuedMessage *)msg_p;
632
633 /* The logic here is:
634 *
635 * 1. If this is a message that will not fit into the remaining
636 * space, then flush.
637 * 2. If the message will now fit into the remaining space,
638 * encrypt, buffer, and loop.
639 * 3. If the message will not fit, then fragment.
640 *
641 * At the end of the function, flush.
642 */
643 if ((msg->len + SSL3_BUFFER_FUDGE) > room_left) {
644 /* The message will not fit into the remaining space, so flush */
645 rv = dtls_SendSavedWriteData(ss);
646 if (rv != SECSuccess)
647 break;
648
649 room_left = ss->ssl3.mtu;
650 }
651
652 if ((msg->len + SSL3_BUFFER_FUDGE) <= room_left) {
653 /* The message will fit, so encrypt and then continue with the
654 * next packet */
655 sent = ssl3_SendRecord(ss, msg->epoch, msg->type,
656 msg->data, msg->len,
657 ssl_SEND_FLAG_FORCE_INTO_BUFFER |
658 ssl_SEND_FLAG_USE_EPOCH);
659 if (sent != msg->len) {
660 rv = SECFailure;
661 if (sent != -1) {
662 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
663 }
664 break;
665 }
666
667 room_left = ss->ssl3.mtu - ss->pendingBuf.len;
668 } else {
669 /* The message will not fit, so fragment.
670 *
671 * TODO(ekr@rtfm.com): OK for now. Arrange to coalesce the
672 * last fragment of this message with the next message
673 * if possible. That would be more efficient.
674 */
675 PRUint32 fragment_offset = 0;
676 unsigned char fragment[DTLS_MAX_MTU]; /* >= than largest
677 * plausible MTU */
678
679 /* Assert that we have already flushed */
680 PORT_Assert(room_left == ss->ssl3.mtu);
681
682 /* Case 3: We now need to fragment this message
683 * DTLS only supports fragmenting handshaking messages */
684 PORT_Assert(msg->type == content_handshake);
685
686 /* The headers consume 12 bytes so the smalles possible
687 * message (i.e., an empty one) is 12 bytes
688 */
689 PORT_Assert(msg->len >= 12);
690
691 while ((fragment_offset + 12) < msg->len) {
692 PRUint32 fragment_len;
693 const unsigned char *content = msg->data + 12;
694 PRUint32 content_len = msg->len - 12;
695
696 /* The reason we use 8 here is that that's the length of
697 * the new DTLS data that we add to the header */
698 fragment_len = PR_MIN(room_left - (SSL3_BUFFER_FUDGE + 8),
699 content_len - fragment_offset);
700 PORT_Assert(fragment_len < DTLS_MAX_MTU - 12);
701 /* Make totally sure that we are within the buffer.
702 * Note that the only way that fragment len could get
703 * adjusted here is if
704 *
705 * (a) we are in release mode so the PORT_Assert is compiled out
706 * (b) either the MTU table is inconsistent with DTLS_MAX_MTU
707 * or ss->ssl3.mtu has become corrupt.
708 */
709 fragment_len = PR_MIN(fragment_len, DTLS_MAX_MTU - 12);
710
711 /* Construct an appropriate-sized fragment */
712 /* Type, length, sequence */
713 PORT_Memcpy(fragment, msg->data, 6);
714
715 /* Offset */
716 fragment[6] = (fragment_offset >> 16) & 0xff;
717 fragment[7] = (fragment_offset >> 8) & 0xff;
718 fragment[8] = (fragment_offset) & 0xff;
719
720 /* Fragment length */
721 fragment[9] = (fragment_len >> 16) & 0xff;
722 fragment[10] = (fragment_len >> 8) & 0xff;
723 fragment[11] = (fragment_len) & 0xff;
724
725 PORT_Memcpy(fragment + 12, content + fragment_offset,
726 fragment_len);
727
728 /*
729 * Send the record. We do this in two stages
730 * 1. Encrypt
731 */
732 sent = ssl3_SendRecord(ss, msg->epoch, msg->type,
733 fragment, fragment_len + 12,
734 ssl_SEND_FLAG_FORCE_INTO_BUFFER |
735 ssl_SEND_FLAG_USE_EPOCH);
736 if (sent != (fragment_len + 12)) {
737 rv = SECFailure;
738 if (sent != -1) {
739 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
740 }
741 break;
742 }
743
744 /* 2. Flush */
745 rv = dtls_SendSavedWriteData(ss);
746 if (rv != SECSuccess)
747 break;
748
749 fragment_offset += fragment_len;
750 }
751 }
752 }
753
754 /* Finally, we need to flush */
755 if (rv == SECSuccess)
756 rv = dtls_SendSavedWriteData(ss);
757
758 /* Give up the locks */
759 ssl_ReleaseSpecReadLock(ss);
760 ssl_ReleaseXmitBufLock(ss);
761
762 return rv;
763 }
764
765 /* Flush the data in the pendingBuf and update the max message sent
766 * so we can adjust the MTU estimate if we need to.
767 * Wrapper for ssl_SendSavedWriteData.
768 *
769 * Called from dtls_TransmitMessageFlight()
770 */
771 static
772 SECStatus dtls_SendSavedWriteData(sslSocket *ss)
773 {
774 PRInt32 sent;
775
776 sent = ssl_SendSavedWriteData(ss);
777 if (sent < 0)
778 return SECFailure;
779
780 /* We should always have complete writes b/c datagram sockets
781 * don't really block */
782 if (ss->pendingBuf.len > 0) {
783 ssl_MapLowLevelError(SSL_ERROR_SOCKET_WRITE_FAILURE);
784 return SECFailure;
785 }
786
787 /* Update the largest message sent so we can adjust the MTU
788 * estimate if necessary */
789 if (sent > ss->ssl3.hs.maxMessageSent)
790 ss->ssl3.hs.maxMessageSent = sent;
791
792 return SECSuccess;
793 }
794
795 /* Compress, MAC, encrypt a DTLS record. Allows specification of
796 * the epoch using epoch value. If use_epoch is PR_TRUE then
797 * we use the provided epoch. If use_epoch is PR_FALSE then
798 * whatever the current value is in effect is used.
799 *
800 * Called from ssl3_SendRecord()
801 */
802 SECStatus
803 dtls_CompressMACEncryptRecord(sslSocket * ss,
804 DTLSEpoch epoch,
805 PRBool use_epoch,
806 SSL3ContentType type,
807 const SSL3Opaque * pIn,
808 PRUint32 contentLen,
809 sslBuffer * wrBuf)
810 {
811 SECStatus rv = SECFailure;
812 ssl3CipherSpec * cwSpec;
813
814 ssl_GetSpecReadLock(ss); /********************************/
815
816 /* The reason for this switch-hitting code is that we might have
817 * a flight of records spanning an epoch boundary, e.g.,
818 *
819 * ClientKeyExchange (epoch = 0)
820 * ChangeCipherSpec (epoch = 0)
821 * Finished (epoch = 1)
822 *
823 * Thus, each record needs a different cipher spec. The information
824 * about which epoch to use is carried with the record.
825 */
826 if (use_epoch) {
827 if (ss->ssl3.cwSpec->epoch == epoch)
828 cwSpec = ss->ssl3.cwSpec;
829 else if (ss->ssl3.pwSpec->epoch == epoch)
830 cwSpec = ss->ssl3.pwSpec;
831 else
832 cwSpec = NULL;
833 } else {
834 cwSpec = ss->ssl3.cwSpec;
835 }
836
837 if (cwSpec) {
838 rv = ssl3_CompressMACEncryptRecord(cwSpec, ss->sec.isServer, PR_TRUE,
839 type, pIn, contentLen, wrBuf);
840 } else {
841 PR_NOT_REACHED("Couldn't find a cipher spec matching epoch");
842 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
843 }
844 ssl_ReleaseSpecReadLock(ss); /************************************/
845
846 return rv;
847 }
848
849 /* Start a timer
850 *
851 * Called from:
852 * dtls_HandleHandshake()
853 * dtls_FlushHAndshake()
854 * dtls_RestartTimer()
855 */
856 SECStatus
857 dtls_StartTimer(sslSocket *ss, DTLSTimerCb cb)
858 {
859 PORT_Assert(ss->ssl3.hs.rtTimerCb == NULL);
860
861 ss->ssl3.hs.rtTimerStarted = PR_IntervalNow();
862 ss->ssl3.hs.rtTimerCb = cb;
863
864 return SECSuccess;
865 }
866
867 /* Restart a timer with optional backoff
868 *
869 * Called from dtls_RetransmitTimerExpiredCb()
870 */
871 SECStatus
872 dtls_RestartTimer(sslSocket *ss, PRBool backoff, DTLSTimerCb cb)
873 {
874 if (backoff) {
875 ss->ssl3.hs.rtTimeoutMs *= 2;
876 if (ss->ssl3.hs.rtTimeoutMs > MAX_DTLS_TIMEOUT_MS)
877 ss->ssl3.hs.rtTimeoutMs = MAX_DTLS_TIMEOUT_MS;
878 }
879
880 return dtls_StartTimer(ss, cb);
881 }
882
883 /* Cancel a pending timer
884 *
885 * Called from:
886 * dtls_HandleHandshake()
887 * dtls_CheckTimer()
888 */
889 void
890 dtls_CancelTimer(sslSocket *ss)
891 {
892 PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
893
894 ss->ssl3.hs.rtTimerCb = NULL;
895 }
896
897 /* Check the pending timer and fire the callback if it expired
898 *
899 * Called from ssl3_GatherCompleteHandshake()
900 */
901 void
902 dtls_CheckTimer(sslSocket *ss)
903 {
904 if (!ss->ssl3.hs.rtTimerCb)
905 return;
906
907 if ((PR_IntervalNow() - ss->ssl3.hs.rtTimerStarted) >
908 PR_MillisecondsToInterval(ss->ssl3.hs.rtTimeoutMs)) {
909 /* Timer has expired */
910 DTLSTimerCb cb = ss->ssl3.hs.rtTimerCb;
911
912 /* Cancel the timer so that we can call the CB safely */
913 dtls_CancelTimer(ss);
914
915 /* Now call the CB */
916 cb(ss);
917 }
918 }
919
920 /* The callback to fire when the holddown timer for the Finished
921 * message expires and we can delete it
922 *
923 * Called from dtls_CheckTimer()
924 */
925 void
926 dtls_FinishedTimerCb(sslSocket *ss)
927 {
928 ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_FALSE);
929 }
930
931 /* Cancel the Finished hold-down timer and destroy the
932 * pending cipher spec. Note that this means that
933 * successive rehandshakes will fail if the Finished is
934 * lost.
935 *
936 * TODO(ekr@rtfm.com): OK for now. Figure out how to
937 * handle the combination of Finished lost and rehandshake
938 */
939 void
940 dtls_RehandshakeCleanup(sslSocket *ss)
941 {
942 dtls_CancelTimer(ss);
943 ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_FALSE);
944 }
945
946 /* Set the MTU to the next step less than or equal to the
947 * advertised value. Also used to downgrade the MTU by
948 * doing dtls_SetMTU(ss, biggest packet set).
949 *
950 * Passing 0 means set this to the largest MTU known
951 * (effectively resetting the PMTU backoff value).
952 *
953 * Called by:
954 * ssl3_InitState()
955 * dtls_RetransmitTimerExpiredCb()
956 */
957 void
958 dtls_SetMTU(sslSocket *ss, PRUint16 advertised)
959 {
960 int i;
961
962 if (advertised == 0) {
963 ss->ssl3.mtu = COMMON_MTU_VALUES[0];
964 SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
965 return;
966 }
967
968 for (i = 0; i < PR_ARRAY_SIZE(COMMON_MTU_VALUES); i++) {
969 if (COMMON_MTU_VALUES[i] <= advertised) {
970 ss->ssl3.mtu = COMMON_MTU_VALUES[i];
971 SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
972 return;
973 }
974 }
975
976 /* Fallback */
977 ss->ssl3.mtu = COMMON_MTU_VALUES[PR_ARRAY_SIZE(COMMON_MTU_VALUES)-1];
978 SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
979 }
980
981 /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a
982 * DTLS hello_verify_request
983 * Caller must hold Handshake and RecvBuf locks.
984 */
985 SECStatus
986 dtls_HandleHelloVerifyRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
987 {
988 int errCode = SSL_ERROR_RX_MALFORMED_HELLO_VERIFY_REQUEST;
989 SECStatus rv;
990 PRInt32 temp;
991 SECItem cookie = {siBuffer, NULL, 0};
992 SSL3AlertDescription desc = illegal_parameter;
993
994 SSL_TRC(3, ("%d: SSL3[%d]: handle hello_verify_request handshake",
995 SSL_GETPID(), ss->fd));
996 PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
997 PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
998
999 if (ss->ssl3.hs.ws != wait_server_hello) {
1000 errCode = SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST;
1001 desc = unexpected_message;
1002 goto alert_loser;
1003 }
1004
1005 /* The version */
1006 temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
1007 if (temp < 0) {
1008 goto loser; /* alert has been sent */
1009 }
1010
1011 if (temp != SSL_LIBRARY_VERSION_DTLS_1_0_WIRE) {
1012 /* Note: this will need adjustment for DTLS 1.2 per Section 4.2.1 */
1013 goto alert_loser;
1014 }
1015
1016 /* The cookie */
1017 rv = ssl3_ConsumeHandshakeVariable(ss, &cookie, 1, &b, &length);
1018 if (rv != SECSuccess) {
1019 goto loser; /* alert has been sent */
1020 }
1021 if (cookie.len > DTLS_COOKIE_BYTES) {
1022 desc = decode_error;
1023 goto alert_loser; /* malformed. */
1024 }
1025
1026 PORT_Memcpy(ss->ssl3.hs.cookie, cookie.data, cookie.len);
1027 ss->ssl3.hs.cookieLen = cookie.len;
1028
1029
1030 ssl_GetXmitBufLock(ss); /*******************************/
1031
1032 /* Now re-send the client hello */
1033 rv = ssl3_SendClientHello(ss, PR_TRUE);
1034
1035 ssl_ReleaseXmitBufLock(ss); /*******************************/
1036
1037 if (rv == SECSuccess)
1038 return rv;
1039
1040 alert_loser:
1041 (void)SSL3_SendAlert(ss, alert_fatal, desc);
1042
1043 loser:
1044 errCode = ssl_MapLowLevelError(errCode);
1045 return SECFailure;
1046 }
1047
1048 /* Initialize the DTLS anti-replay window
1049 *
1050 * Called from:
1051 * ssl3_SetupPendingCipherSpec()
1052 * ssl3_InitCipherSpec()
1053 */
1054 void
1055 dtls_InitRecvdRecords(DTLSRecvdRecords *records)
1056 {
1057 PORT_Memset(records->data, 0, sizeof(records->data));
1058 records->left = 0;
1059 records->right = DTLS_RECVD_RECORDS_WINDOW - 1;
1060 }
1061
1062 /*
1063 * Has this DTLS record been received? Return values are:
1064 * -1 -- out of range to the left
1065 * 0 -- not received yet
1066 * 1 -- replay
1067 *
1068 * Called from: dtls_HandleRecord()
1069 */
1070 int
1071 dtls_RecordGetRecvd(DTLSRecvdRecords *records, PRUint64 seq)
1072 {
1073 PRUint64 offset;
1074
1075 /* Out of range to the left */
1076 if (seq < records->left) {
1077 return -1;
1078 }
1079
1080 /* Out of range to the right; since we advance the window on
1081 * receipt, that means that this packet has not been received
1082 * yet */
1083 if (seq > records->right)
1084 return 0;
1085
1086 offset = seq % DTLS_RECVD_RECORDS_WINDOW;
1087
1088 return !!(records->data[offset / 8] & (1 << (offset % 8)));
1089 }
1090
1091 /* Update the DTLS anti-replay window
1092 *
1093 * Called from ssl3_HandleRecord()
1094 */
1095 void
1096 dtls_RecordSetRecvd(DTLSRecvdRecords *records, PRUint64 seq)
1097 {
1098 PRUint64 offset;
1099
1100 if (seq < records->left)
1101 return;
1102
1103 if (seq > records->right) {
1104 PRUint64 new_left;
1105 PRUint64 new_right;
1106 PRUint64 right;
1107
1108 /* Slide to the right; this is the tricky part
1109 *
1110 * 1. new_top is set to have room for seq, on the
1111 * next byte boundary by setting the right 8
1112 * bits of seq
1113 * 2. new_left is set to compensate.
1114 * 3. Zero all bits between top and new_top. Since
1115 * this is a ring, this zeroes everything as-yet
1116 * unseen. Because we always operate on byte
1117 * boundaries, we can zero one byte at a time
1118 */
1119 new_right = seq | 0x07;
1120 new_left = (new_right - DTLS_RECVD_RECORDS_WINDOW) + 1;
1121
1122 for (right = records->right + 8; right <= new_right; right += 8) {
1123 offset = right % DTLS_RECVD_RECORDS_WINDOW;
1124 records->data[offset / 8] = 0;
1125 }
1126
1127 records->right = new_right;
1128 records->left = new_left;
1129 }
1130
1131 offset = seq % DTLS_RECVD_RECORDS_WINDOW;
1132
1133 records->data[offset / 8] |= (1 << (offset % 8));
1134 }
1135
1136 SECStatus
1137 DTLS_GetTimeout(PRFileDesc *socket, PRIntervalTime *timeout)
1138 {
1139 sslSocket * ss = NULL;
1140 PRIntervalTime elapsed;
1141 PRIntervalTime desired;
1142
1143 ss = ssl_FindSocket(socket);
1144
1145 if (!ss)
1146 return SECFailure;
1147
1148 if (!IS_DTLS(ss))
1149 return SECFailure;
1150
1151 if (!ss->ssl3.hs.rtTimerCb)
1152 return SECFailure;
1153
1154 elapsed = PR_IntervalNow() - ss->ssl3.hs.rtTimerStarted;
1155 desired = PR_MillisecondsToInterval(ss->ssl3.hs.rtTimeoutMs);
1156 if (elapsed > desired) {
1157 /* Timer expired */
1158 *timeout = PR_INTERVAL_NO_WAIT;
1159 } else {
1160 *timeout = desired - elapsed;
1161 }
1162
1163 return SECSuccess;
1164 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698