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

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

Powered by Google App Engine
This is Rietveld 408576698