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

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: Remove an extra 'the' 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 /* XXX 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));
ekr 2012/03/26 21:49:18 A lot of the existing code has these extra spaces
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 * XXX OK for now. Maybe do something smarter at some point?
361 */
362 } else {
363 /* Case 1
364 *
365 * Buffer the fragment for reassembly
366 */
367 /* Make room for the message */
368 if (ss->ssl3.hs.recvdHighWater == -1) {
369 PRUint32 map_length = OFFSET_BYTE(message_length) + 1;
370
371 rv = sslBuffer_Grow(&ss->ssl3.hs.msg_body, message_length);
372 if (rv != SECSuccess)
373 break;
374 /* Make room for the fragment map */
375 rv = sslBuffer_Grow(&ss->ssl3.hs.recvdFragments,
376 map_length);
377 if (rv != SECSuccess)
378 break;
379
380 /* Reset the reassembly map */
381 ss->ssl3.hs.recvdHighWater = 0;
382 PORT_Memset(ss->ssl3.hs.recvdFragments.buf, 0,
383 ss->ssl3.hs.recvdFragments.space);
384 ss->ssl3.hs.msg_type = (SSL3HandshakeType)type;
385 ss->ssl3.hs.msg_len = message_length;
386 }
387
388 /* If we have a message length mismatch, abandon the reassembly
389 * in progress and hope that the next retransmit will give us
390 * something sane
391 */
392 if (message_length != ss->ssl3.hs.msg_len) {
393 ss->ssl3.hs.recvdHighWater = -1;
394 PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
395 rv = SECFailure;
396 break;
397 }
398
399 /* Now copy this fragment into the buffer */
400 PORT_Assert((fragment_offset + fragment_length) <=
401 ss->ssl3.hs.msg_body.space);
402 PORT_Memcpy(ss->ssl3.hs.msg_body.buf + fragment_offset,
403 buf.buf, fragment_length);
404
405 /* This logic is a bit tricky. We have two values for
406 * reassembly state:
407 *
408 * - recvdHighWater contains the highest contiguous number of
409 * bytes received
410 * - recvdFragments contains a bitmask of packets received
411 * above recvdHighWater
412 *
413 * This avoids having to fill in the bitmask in the common
414 * case of adjacent fragments received in sequence
415 */
416 if (fragment_offset <= ss->ssl3.hs.recvdHighWater) {
417 /* Either this is the adjacent fragment or an overlapping
418 * fragment */
419 ss->ssl3.hs.recvdHighWater = fragment_offset +
420 fragment_length;
421 } else {
422 for (offset = fragment_offset;
423 offset < fragment_offset + fragment_length;
424 offset++) {
425 ss->ssl3.hs.recvdFragments.buf[OFFSET_BYTE(offset)] |=
426 OFFSET_MASK(offset);
427 }
428 }
429
430 /* Now figure out the new high water mark if appropriate */
431 for (offset = ss->ssl3.hs.recvdHighWater;
432 offset < ss->ssl3.hs.msg_len; offset++) {
433 /* Note that this loop is not efficient, since it counts
434 * bit by bit. If we have a lot of out-of-order packets,
435 * we should optimize this */
436 if (ss->ssl3.hs.recvdFragments.buf[OFFSET_BYTE(offset)] &
437 OFFSET_MASK(offset)) {
438 ss->ssl3.hs.recvdHighWater++;
439 } else {
440 break;
441 }
442 }
443
444 /* If we have all the bytes, then we are good to go */
445 if (ss->ssl3.hs.recvdHighWater == ss->ssl3.hs.msg_len) {
446 ss->ssl3.hs.recvdHighWater = -1;
447
448 rv = ssl3_HandleHandshakeMessage(ss,
449 ss->ssl3.hs.msg_body.buf,
450 ss->ssl3.hs.msg_len);
451 if (rv == SECFailure)
452 break; /* Skip rest of record */
453
454 /* At this point we are advancing our state machine, so
455 * we can free our last flight of messages */
456 dtls_FreeHandshakeMessages(ss->ssl3.hs.lastMessageFlight);
457 dtls_CancelTimer(ss);
458
459 /* If there have been no retries this time, reset the
460 * timer value to the default per Section 4.2.4.1 */
461 if (ss->ssl3.hs.rtRetries == 0) {
462 ss->ssl3.hs.rtTimeoutMs = INITIAL_DTLS_TIMEOUT_MS;
463 }
464 }
465 }
466 }
467
ekr 2012/03/26 21:49:18 Did you reverse these for a technical reason or is
wtc 2012/03/27 00:28:25 It is just aesthetic.
468 buf.buf += fragment_length;
469 buf.len -= fragment_length;
470 }
471
472 origBuf->len = 0; /* So ssl3_GatherAppDataRecord will keep looping. */
473
474 /* XXX OK for now. In future handle rv == SECWouldBlock safely in order
475 * to deal with asynchronous certificate verification */
476 return rv;
477 }
478
479 /* Enqueue a message (either handshake or CCS)
480 *
481 * Called from:
482 * dtls_StageHandshakeMessage()
483 * ssl3_SendChangeCipherSpecs()
484 */
485 SECStatus dtls_QueueMessage(sslSocket *ss, SSL3ContentType type,
486 const SSL3Opaque *pIn, PRInt32 nIn)
487 {
488 SECStatus rv = SECSuccess;
489 DTLSQueuedMessage *msg = NULL;
490
491 PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
492 PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
493
494 msg = dtls_AllocQueuedMessage(ss->ssl3.cwSpec->epoch, type, pIn, nIn);
495
496 if (!msg) {
497 PORT_SetError(SEC_ERROR_NO_MEMORY);
498 rv = SECFailure;
499 } else {
500 PR_APPEND_LINK(&msg->link, ss->ssl3.hs.lastMessageFlight);
501 }
502
503 return rv;
504 }
505
506 /* Add DTLS handshake message to the pending queue
507 * Empty the sendBuf buffer.
508 * This function returns SECSuccess or SECFailure, never SECWouldBlock.
509 * Always set sendBuf.len to 0, even when returning SECFailure.
510 *
511 * Called from:
512 * ssl3_AppendHandshakeHeader()
513 * dtls_FlushHandshake()
514 */
515 SECStatus
516 dtls_StageHandshakeMessage(sslSocket *ss)
517 {
518 SECStatus rv = SECSuccess;
519
520 PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
521 PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
522
523 /* This function is sometimes called when no data is actually to
524 * be staged, so just return SECSuccess. */
525 if (!ss->sec.ci.sendBuf.buf || !ss->sec.ci.sendBuf.len)
526 return rv;
527
528 rv = dtls_QueueMessage(ss, content_handshake,
529 ss->sec.ci.sendBuf.buf, ss->sec.ci.sendBuf.len);
530
531 /* Whether we succeeded or failed, toss the old handshake data. */
532 ss->sec.ci.sendBuf.len = 0;
533 return rv;
534 }
535
536 /* Enqueue the handshake message in sendBuf (if any) and then
537 * transmit the resulting flight of handshake messages.
538 *
539 * Called from:
540 * ssl3_FlushHandshake()
541 */
542 SECStatus
543 dtls_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags)
544 {
545 SECStatus rv = SECSuccess;
546
547 PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
548 PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
549
550 rv = dtls_StageHandshakeMessage(ss);
551 if (rv != SECSuccess)
552 return rv;
553
554 if (!(flags & ssl_SEND_FLAG_FORCE_INTO_BUFFER)) {
555 rv = dtls_TransmitMessageFlight(ss);
556 if (rv != SECSuccess)
557 return rv;
558
559 if (!(flags & ssl_SEND_FLAG_NO_RETRANSMIT)) {
560 ss->ssl3.hs.rtRetries = 0;
561 rv = dtls_StartTimer(ss, dtls_RetransmitTimerExpiredCb);
562 }
563 }
564
565 return rv;
566 }
567
568 /* The callback for when the retransmit timer expires
569 *
570 * Called from:
571 * dtls_CheckTimer()
572 * dtls_HandleHandshake()
573 */
574 static void
575 dtls_RetransmitTimerExpiredCb(sslSocket *ss)
576 {
577 SECStatus rv = SECFailure;
578
579 ss->ssl3.hs.rtRetries++;
580
581 if (!(ss->ssl3.hs.rtRetries % 3)) {
582 /* If one of the messages was potentially greater than > MTU,
583 * then downgrade. Do this every time we have retransmitted a
584 * message twice, per RFC 6347 Sec. 4.1.1 */
585 dtls_SetMTU(ss, ss->ssl3.hs.maxMessageSent - 1);
586 }
587
588 rv = dtls_TransmitMessageFlight(ss);
589 if (rv == SECSuccess) {
590
591 /* Re-arm the timer */
592 rv = dtls_RestartTimer(ss, PR_TRUE, dtls_RetransmitTimerExpiredCb);
593 }
594
595 if (rv == SECFailure) {
596 /* XXX OK for now. In future maybe signal the stack that we couldn't
597 * transmit. For now, let the read handle any real network errors */
598 }
599 }
600
601 /* Transmit a flight of handshake messages, stuffing them
602 * into as few records as seems reasonable
603 *
604 * Called from:
605 * dtls_FlushHandshake()
606 * dtls_RetransmitTimerExpiredCb()
607 */
608 static SECStatus
609 dtls_TransmitMessageFlight(sslSocket *ss)
610 {
611 SECStatus rv = SECSuccess;
612 PRCList *msg_p;
613 PRUint16 room_left = ss->ssl3.mtu;
614 PRInt32 sent;
615
616 ssl_GetXmitBufLock(ss);
617 ssl_GetSpecReadLock(ss);
618
619 /* DTLS does not buffer its handshake messages in
620 * ss->pendingBuf, but rather in the lastMessageFlight
621 * structure. This is just a sanity check that
622 * some programming error hasn't inadvertantly
623 * stuffed something in ss->pendingBuf
624 */
625 PORT_Assert(!ss->pendingBuf.len);
626 for (msg_p = PR_LIST_HEAD(ss->ssl3.hs.lastMessageFlight);
627 msg_p != ss->ssl3.hs.lastMessageFlight;
628 msg_p = PR_NEXT_LINK(msg_p)) {
629 DTLSQueuedMessage *msg = (DTLSQueuedMessage *)msg_p;
630
631 /* The logic here is:
632 *
633 * 1. If this is a message that will not fit into the remaining
634 * space, then flush.
635 * 2. If the message will now fit into the remaining space,
636 * encrypt, buffer, and loop.
637 * 3. If the message will not fit, then fragment.
638 *
639 * At the end of the function, flush.
640 */
641 if ((msg->len + SSL3_BUFFER_FUDGE) > room_left) {
642 /* The message will not fit into the remaining space, so flush */
643 rv = dtls_SendSavedWriteData(ss);
644 if (rv != SECSuccess)
645 break;
646
647 room_left = ss->ssl3.mtu;
648 }
649
650 if ((msg->len + SSL3_BUFFER_FUDGE) <= room_left) {
651 /* The message will fit, so encrypt and then continue with the
652 * next packet */
653 sent = ssl3_SendRecord(ss, msg->epoch, msg->type,
654 msg->data, msg->len,
655 ssl_SEND_FLAG_FORCE_INTO_BUFFER |
656 ssl_SEND_FLAG_USE_EPOCH);
657 if (sent != msg->len) {
658 rv = SECFailure;
659 if (sent != -1) {
660 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
661 }
662 break;
663 }
664
665 room_left = ss->ssl3.mtu - ss->pendingBuf.len;
666 } else {
667 /* The message will not fit, so fragment.
668 *
669 * XXX OK for now. Arrange to coalesce the last fragment
670 * of this message with the next message if possible.
671 * That would be more efficient.
672 */
673 PRUint32 fragment_offset = 0;
674 unsigned char fragment[DTLS_MAX_MTU]; /* >= than largest
675 * plausible MTU */
676
677 /* Assert that we have already flushed */
678 PORT_Assert(room_left == ss->ssl3.mtu);
679
680 /* Case 3: We now need to fragment this message
681 * DTLS only supports fragmenting handshaking messages */
682 PORT_Assert(msg->type == content_handshake);
683
684 /* The headers consume 12 bytes so the smalles possible
685 * message (i.e., an empty one) is 12 bytes
686 */
687 PORT_Assert(msg->len >= 12);
688
689 while ((fragment_offset + 12) < msg->len) {
690 PRUint32 fragment_len;
691 const unsigned char *content = msg->data + 12;
692 PRUint32 content_len = msg->len - 12;
693
694 /* The reason we use 8 here is that that's the length of
695 * the new DTLS data that we add to the header */
696 fragment_len = PR_MIN(room_left - (SSL3_BUFFER_FUDGE + 8),
697 content_len - fragment_offset);
698 PORT_Assert(fragment_len < DTLS_MAX_MTU - 12);
699 /* Make totally sure that we are within the buffer.
700 * Note that the only way that fragment len could get
701 * adjusted here is if
702 *
703 * (a) we are in release mode so the PORT_Assert is compiled out
704 * (b) either the MTU table is inconsistent with DTLS_MAX_MTU
705 * or ss->ssl3.mtu has become corrupt.
706 */
707 fragment_len = PR_MIN(fragment_len, DTLS_MAX_MTU - 12);
708
709 /* Construct an appropriate-sized fragment */
710 /* Type, length, sequence */
711 PORT_Memcpy(fragment, msg->data, 6);
712
713 /* Offset */
714 fragment[6] = (fragment_offset >> 16) & 0xff;
715 fragment[7] = (fragment_offset >> 8) & 0xff;
716 fragment[8] = (fragment_offset) & 0xff;
717
718 /* Fragment length */
719 fragment[9] = (fragment_len >> 16) & 0xff;
720 fragment[10] = (fragment_len >> 8) & 0xff;
721 fragment[11] = (fragment_len) & 0xff;
722
723 PORT_Memcpy(fragment + 12, content + fragment_offset,
724 fragment_len);
725
726 /*
727 * Send the record. We do this in two stages
728 * 1. Encrypt
729 */
730 sent = ssl3_SendRecord(ss, msg->epoch, msg->type,
731 fragment, fragment_len + 12,
732 ssl_SEND_FLAG_FORCE_INTO_BUFFER |
733 ssl_SEND_FLAG_USE_EPOCH);
734 if (sent != (fragment_len + 12)) {
735 rv = SECFailure;
736 if (sent != -1) {
737 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
738 }
739 break;
740 }
741
742 /* 2. Flush */
743 rv = dtls_SendSavedWriteData(ss);
744 if (rv != SECSuccess)
745 break;
746
747 fragment_offset += fragment_len;
748 }
749 }
750 }
751
752 /* Finally, we need to flush */
753 if (rv == SECSuccess)
754 rv = dtls_SendSavedWriteData(ss);
755
756 /* Give up the locks */
757 ssl_ReleaseSpecReadLock(ss);
758 ssl_ReleaseXmitBufLock(ss);
759
760 return rv;
761 }
762
763 /* Flush the data in the pendingBuf and update the max message sent
764 * so we can adjust the MTU estimate if we need to.
765 * Wrapper for ssl_SendSavedWriteData.
766 *
767 * Called from dtls_TransmitMessageFlight()
768 */
769 static
770 SECStatus dtls_SendSavedWriteData(sslSocket *ss)
771 {
772 PRInt32 sent;
773
774 sent = ssl_SendSavedWriteData(ss);
775 if (sent < 0)
776 return SECFailure;
777
778 /* We should always have complete writes b/c datagram sockets
779 * don't really block */
780 if (ss->pendingBuf.len > 0) {
781 ssl_MapLowLevelError(SSL_ERROR_SOCKET_WRITE_FAILURE);
782 return SECFailure;
783 }
784
785 /* Update the largest message sent so we can adjust the MTU
786 * estimate if necessary */
787 if (sent > ss->ssl3.hs.maxMessageSent)
788 ss->ssl3.hs.maxMessageSent = sent;
789
790 return SECSuccess;
791 }
792
793 /* Compress, MAC, encrypt a DTLS record. Allows specification of
794 * the epoch using epoch value. If use_epoch is PR_TRUE then
795 * we use the provided epoch. If use_epoch is PR_FALSE then
796 * whatever the current value is in effect is used.
797 *
798 * Called from ssl3_SendRecord()
799 */
800 SECStatus
801 dtls_CompressMACEncryptRecord(sslSocket * ss,
802 DTLSEpoch epoch,
803 PRBool use_epoch,
804 SSL3ContentType type,
805 const SSL3Opaque * pIn,
806 PRUint32 contentLen,
807 sslBuffer * wrBuf)
808 {
809 SECStatus rv = SECFailure;
810 ssl3CipherSpec * cwSpec;
811
812 ssl_GetSpecReadLock(ss); /********************************/
813
814 /* The reason for this switch-hitting code is that we might have
815 * a flight of records spanning an epoch boundary, e.g.,
816 *
817 * ClientKeyExchange (epoch = 0)
818 * ChangeCipherSpec (epoch = 0)
819 * Finished (epoch = 1)
820 *
821 * Thus, each record needs a different cipher spec. The information
822 * about which epoch to use is carried with the record.
823 */
824 if (use_epoch) {
825 if (ss->ssl3.cwSpec->epoch == epoch)
826 cwSpec = ss->ssl3.cwSpec;
827 else if (ss->ssl3.pwSpec->epoch == epoch)
828 cwSpec = ss->ssl3.pwSpec;
829 else
830 cwSpec = NULL;
831 } else {
832 cwSpec = ss->ssl3.cwSpec;
833 }
834
835 if (cwSpec) {
836 rv = ssl3_CompressMACEncryptRecord(cwSpec, ss->sec.isServer, PR_TRUE,
837 type, pIn, contentLen, wrBuf);
838 } else {
839 PR_NOT_REACHED("Couldn't find a cipher spec matching epoch");
840 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
841 }
842 ssl_ReleaseSpecReadLock(ss); /************************************/
843
844 return rv;
845 }
846
847 /* Start a timer
848 *
849 * Called from:
850 * dtls_HandleHandshake()
851 * dtls_FlushHAndshake()
852 * dtls_RestartTimer()
853 */
854 SECStatus
855 dtls_StartTimer(sslSocket *ss, DTLSTimerCb cb)
856 {
857 PORT_Assert(ss->ssl3.hs.rtTimerCb == NULL);
858
859 ss->ssl3.hs.rtTimerStarted = PR_IntervalNow();
860 ss->ssl3.hs.rtTimerCb = cb;
861
862 return SECSuccess;
863 }
864
865 /* Restart a timer with optional backoff
866 *
867 * Called from dtls_RetransmitTimerExpiredCb()
868 */
869 SECStatus
870 dtls_RestartTimer(sslSocket *ss, PRBool backoff, DTLSTimerCb cb)
871 {
872 if (backoff) {
873 ss->ssl3.hs.rtTimeoutMs *= 2;
874 if (ss->ssl3.hs.rtTimeoutMs > MAX_DTLS_TIMEOUT_MS)
875 ss->ssl3.hs.rtTimeoutMs = MAX_DTLS_TIMEOUT_MS;
876 }
877
878 return dtls_StartTimer(ss, cb);
879 }
880
881 /* Cancel a pending timer
882 *
883 * Called from:
884 * dtls_HandleHandshake()
885 * dtls_CheckTimer()
886 */
887 void
888 dtls_CancelTimer(sslSocket *ss)
889 {
890 PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
891
892 ss->ssl3.hs.rtTimerCb = NULL;
893 }
894
895 /* Check the pending timer and fire the callback if it expired
896 *
897 * Called from ssl3_GatherCompleteHandshake()
898 */
899 void
900 dtls_CheckTimer(sslSocket *ss)
901 {
902 if (!ss->ssl3.hs.rtTimerCb)
903 return;
904
905 if ((PR_IntervalNow() - ss->ssl3.hs.rtTimerStarted) >
906 PR_MillisecondsToInterval(ss->ssl3.hs.rtTimeoutMs)) {
907 /* Timer has expired */
908 DTLSTimerCb cb = ss->ssl3.hs.rtTimerCb;
909
910 /* Cancel the timer so that we can call the CB safely */
911 dtls_CancelTimer(ss);
912
913 /* Now call the CB */
914 cb(ss);
915 }
916 }
917
918 /* The callback to fire when the holddown timer for the Finished
919 * message expires and we can delete it
920 *
921 * Called from dtls_CheckTimer()
922 */
923 void
924 dtls_FinishedTimerCb(sslSocket *ss)
925 {
926 ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_FALSE);
927 }
928
929 /* Cancel the Finished hold-down timer and destroy the
930 * pending cipher spec. Note that this means that
931 * successive rehandshakes will fail if the Finished is
932 * lost.
933 *
934 * XXX OK for now. Figure out how to handle the combination
935 * of Finished lost and rehandshake
936 */
937 void
938 dtls_RehandshakeCleanup(sslSocket *ss)
939 {
940 dtls_CancelTimer(ss);
941 ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_FALSE);
942 }
943
944 /* Set the MTU to the next step less than or equal to the
945 * advertised value. Also used to downgrade the MTU by
946 * doing dtls_SetMTU(ss, biggest packet set).
947 *
948 * Passing 0 means set this to the largest MTU known
949 * (effectively resetting the PMTU backoff value).
950 *
951 * Called by:
952 * ssl3_InitState()
953 * dtls_RetransmitTimerExpiredCb()
954 */
955 void
956 dtls_SetMTU(sslSocket *ss, PRUint16 advertised)
957 {
958 int i;
959
960 if (advertised == 0) {
961 ss->ssl3.mtu = COMMON_MTU_VALUES[0];
962 SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
963 return;
964 }
965
966 for (i = 0; i < PR_ARRAY_SIZE(COMMON_MTU_VALUES); i++) {
967 if (COMMON_MTU_VALUES[i] <= advertised) {
968 ss->ssl3.mtu = COMMON_MTU_VALUES[i];
969 SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
970 return;
971 }
972 }
973
974 /* Fallback */
975 ss->ssl3.mtu = COMMON_MTU_VALUES[PR_ARRAY_SIZE(COMMON_MTU_VALUES)-1];
976 SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
977 }
978
979 /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a
980 * DTLS hello_verify_request
981 * Caller must hold Handshake and RecvBuf locks.
982 */
983 SECStatus
984 dtls_HandleHelloVerifyRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
985 {
986 int errCode = SSL_ERROR_RX_MALFORMED_HELLO_VERIFY_REQUEST;
987 SECStatus rv;
988 PRInt32 temp;
989 SECItem cookie = {siBuffer, NULL, 0};
990 SSL3AlertDescription desc = illegal_parameter;
991
992 SSL_TRC(3, ("%d: SSL3[%d]: handle hello_verify_request handshake",
993 SSL_GETPID(), ss->fd));
994 PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
995 PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
996
997 if (ss->ssl3.hs.ws != wait_server_hello) {
998 errCode = SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST;
999 desc = unexpected_message;
1000 goto alert_loser;
1001 }
1002
1003 /* The version */
1004 temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
1005 if (temp < 0) {
1006 goto loser; /* alert has been sent */
1007 }
1008
1009 if (temp != SSL_LIBRARY_VERSION_DTLS_1_0_WIRE) {
1010 /* Note: this will need adjustment for DTLS 1.2 per Section 4.2.1 */
1011 goto alert_loser;
1012 }
1013
1014 /* The cookie */
1015 rv = ssl3_ConsumeHandshakeVariable(ss, &cookie, 1, &b, &length);
1016 if (rv != SECSuccess) {
1017 goto loser; /* alert has been sent */
1018 }
1019 if (cookie.len > DTLS_COOKIE_BYTES) {
1020 desc = decode_error;
1021 goto alert_loser; /* malformed. */
1022 }
1023
1024 PORT_Memcpy(ss->ssl3.hs.cookie, cookie.data, cookie.len);
1025 ss->ssl3.hs.cookieLen = cookie.len;
1026
1027
1028 ssl_GetXmitBufLock(ss); /*******************************/
1029
1030 /* Now re-send the client hello */
1031 rv = ssl3_SendClientHello(ss, PR_TRUE);
1032
1033 ssl_ReleaseXmitBufLock(ss); /*******************************/
1034
1035 if (rv == SECSuccess)
1036 return rv;
1037
1038 alert_loser:
1039 (void)SSL3_SendAlert(ss, alert_fatal, desc);
1040
1041 loser:
1042 errCode = ssl_MapLowLevelError(errCode);
1043 return SECFailure;
1044 }
1045
1046 /* Initialize the DTLS anti-replay window
1047 *
1048 * Called from:
1049 * ssl3_SetupPendingCipherSpec()
1050 * ssl3_InitCipherSpec()
1051 */
1052 void
1053 dtls_InitRecvdRecords(DTLSRecvdRecords *records)
1054 {
1055 PORT_Memset(records->data, 0, sizeof(records->data));
1056 records->left = 0;
1057 records->right = DTLS_RECVD_RECORDS_WINDOW - 1;
1058 }
1059
1060 /*
1061 * Has this DTLS record been received? Return values are:
1062 * -1 -- out of range to the left
1063 * 0 -- not received yet
1064 * 1 -- replay
1065 *
1066 * Called from: dtls_HandleRecord()
1067 */
1068 int
1069 dtls_RecordGetRecvd(DTLSRecvdRecords *records, PRUint64 seq)
1070 {
1071 PRUint64 offset;
1072
1073 /* Out of range to the left */
1074 if (seq < records->left) {
1075 return -1;
1076 }
1077
1078 /* Out of range to the right; since we advance the window on
1079 * receipt, that means that this packet has not been received
1080 * yet */
1081 if (seq > records->right)
1082 return 0;
1083
1084 offset = seq % DTLS_RECVD_RECORDS_WINDOW;
1085
1086 return !!(records->data[offset / 8] & (1 << (offset % 8)));
1087 }
1088
1089 /* Update the DTLS anti-replay window
1090 *
1091 * Called from ssl3_HandleRecord()
1092 */
1093 void
1094 dtls_RecordSetRecvd(DTLSRecvdRecords *records, PRUint64 seq)
1095 {
1096 PRUint64 offset;
1097
1098 if (seq < records->left)
1099 return;
1100
1101 if (seq > records->right) {
1102 PRUint64 new_left;
1103 PRUint64 new_right;
1104 PRUint64 right;
1105
1106 /* Slide to the right; this is the tricky part
1107 *
1108 * 1. new_top is set to have room for seq, on the
1109 * next byte boundary by setting the right 8
1110 * bits of seq
1111 * 2. new_left is set to compensate.
1112 * 3. Zero all bits between top and new_top. Since
1113 * this is a ring, this zeroes everything as-yet
1114 * unseen. Because we always operate on byte
1115 * boundaries, we can zero one byte at a time
1116 */
1117 new_right = seq | 0x07;
1118 new_left = (new_right - DTLS_RECVD_RECORDS_WINDOW) + 1;
1119
1120 for (right = records->right + 8; right <= new_right; right += 8) {
1121 offset = right % DTLS_RECVD_RECORDS_WINDOW;
1122 records->data[offset / 8] = 0;
1123 }
1124
1125 records->right = new_right;
1126 records->left = new_left;
1127 }
1128
1129 offset = seq % DTLS_RECVD_RECORDS_WINDOW;
1130
1131 records->data[offset / 8] |= (1 << (offset % 8));
1132 }
1133
1134 SECStatus
1135 DTLS_GetTimeout(PRFileDesc *socket, PRIntervalTime *timeout)
1136 {
1137 sslSocket * ss = NULL;
1138 PRIntervalTime elapsed;
1139 PRIntervalTime desired;
1140
1141 ss = ssl_FindSocket(socket);
1142
1143 if (!ss)
1144 return SECFailure;
1145
1146 if (!IS_DTLS(ss))
1147 return SECFailure;
1148
1149 if (!ss->ssl3.hs.rtTimerCb)
1150 return SECFailure;
1151
1152 elapsed = PR_IntervalNow() - ss->ssl3.hs.rtTimerStarted;
1153 desired = PR_MillisecondsToInterval(ss->ssl3.hs.rtTimeoutMs);
1154 if (elapsed > desired) {
1155 /* Timer expired */
1156 *timeout = PR_INTERVAL_NO_WAIT;
1157 } else {
1158 *timeout = desired - elapsed;
1159 }
1160
1161 return SECSuccess;
1162 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698