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

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

Powered by Google App Engine
This is Rietveld 408576698