Add explicit |forceOnlineSignin| to user pod status
[chromium-blink-merge.git] / net / third_party / nss / ssl / dtlscon.c
blob78371e62a6c02228002b06a3ec5e19317297b7ef
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 /*
6 * DTLS Protocol
7 */
9 #include "ssl.h"
10 #include "sslimpl.h"
11 #include "sslproto.h"
13 #ifndef PR_ARRAY_SIZE
14 #define PR_ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
15 #endif
17 static SECStatus dtls_TransmitMessageFlight(sslSocket *ss);
18 static void dtls_RetransmitTimerExpiredCb(sslSocket *ss);
19 static SECStatus dtls_SendSavedWriteData(sslSocket *ss);
21 /* -28 adjusts for the IP/UDP header */
22 static const PRUint16 COMMON_MTU_VALUES[] = {
23 1500 - 28, /* Ethernet MTU */
24 1280 - 28, /* IPv6 minimum MTU */
25 576 - 28, /* Common assumption */
26 256 - 28 /* We're in serious trouble now */
29 #define DTLS_COOKIE_BYTES 32
31 /* List copied from ssl3con.c:cipherSuites */
32 static const ssl3CipherSuite nonDTLSSuites[] = {
33 #ifdef NSS_ENABLE_ECC
34 TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
35 TLS_ECDHE_RSA_WITH_RC4_128_SHA,
36 #endif /* NSS_ENABLE_ECC */
37 TLS_DHE_DSS_WITH_RC4_128_SHA,
38 #ifdef NSS_ENABLE_ECC
39 TLS_ECDH_RSA_WITH_RC4_128_SHA,
40 TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
41 #endif /* NSS_ENABLE_ECC */
42 SSL_RSA_WITH_RC4_128_MD5,
43 SSL_RSA_WITH_RC4_128_SHA,
44 TLS_RSA_EXPORT1024_WITH_RC4_56_SHA,
45 SSL_RSA_EXPORT_WITH_RC4_40_MD5,
46 0 /* End of list marker */
49 /* Map back and forth between TLS and DTLS versions in wire format.
50 * Mapping table is:
52 * TLS DTLS
53 * 1.1 (0302) 1.0 (feff)
55 SSL3ProtocolVersion
56 dtls_TLSVersionToDTLSVersion(SSL3ProtocolVersion tlsv)
58 /* Anything other than TLS 1.1 is an error, so return
59 * the invalid version ffff. */
60 if (tlsv != SSL_LIBRARY_VERSION_TLS_1_1)
61 return 0xffff;
63 return SSL_LIBRARY_VERSION_DTLS_1_0_WIRE;
66 /* Map known DTLS versions to known TLS versions.
67 * - Invalid versions (< 1.0) return a version of 0
68 * - Versions > known return a version one higher than we know of
69 * to accomodate a theoretically newer version */
70 SSL3ProtocolVersion
71 dtls_DTLSVersionToTLSVersion(SSL3ProtocolVersion dtlsv)
73 if (MSB(dtlsv) == 0xff) {
74 return 0;
77 if (dtlsv == SSL_LIBRARY_VERSION_DTLS_1_0_WIRE)
78 return SSL_LIBRARY_VERSION_TLS_1_1;
80 /* Return a fictional higher version than we know of */
81 return SSL_LIBRARY_VERSION_TLS_1_1 + 1;
84 /* On this socket, Disable non-DTLS cipher suites in the argument's list */
85 SECStatus
86 ssl3_DisableNonDTLSSuites(sslSocket * ss)
88 const ssl3CipherSuite * suite;
90 for (suite = nonDTLSSuites; *suite; ++suite) {
91 SECStatus rv = ssl3_CipherPrefSet(ss, *suite, PR_FALSE);
93 PORT_Assert(rv == SECSuccess); /* else is coding error */
95 return SECSuccess;
98 /* Allocate a DTLSQueuedMessage.
100 * Called from dtls_QueueMessage()
102 static DTLSQueuedMessage *
103 dtls_AllocQueuedMessage(PRUint16 epoch, SSL3ContentType type,
104 const unsigned char *data, PRUint32 len)
106 DTLSQueuedMessage *msg = NULL;
108 msg = PORT_ZAlloc(sizeof(DTLSQueuedMessage));
109 if (!msg)
110 return NULL;
112 msg->data = PORT_Alloc(len);
113 if (!msg->data) {
114 PORT_Free(msg);
115 return NULL;
117 PORT_Memcpy(msg->data, data, len);
119 msg->len = len;
120 msg->epoch = epoch;
121 msg->type = type;
123 return msg;
127 * Free a handshake message
129 * Called from dtls_FreeHandshakeMessages()
131 static void
132 dtls_FreeHandshakeMessage(DTLSQueuedMessage *msg)
134 if (!msg)
135 return;
137 PORT_ZFree(msg->data, msg->len);
138 PORT_Free(msg);
142 * Free a list of handshake messages
144 * Called from:
145 * dtls_HandleHandshake()
146 * ssl3_DestroySSL3Info()
148 void
149 dtls_FreeHandshakeMessages(PRCList *list)
151 PRCList *cur_p;
153 while (!PR_CLIST_IS_EMPTY(list)) {
154 cur_p = PR_LIST_TAIL(list);
155 PR_REMOVE_LINK(cur_p);
156 dtls_FreeHandshakeMessage((DTLSQueuedMessage *)cur_p);
160 /* Called only from ssl3_HandleRecord, for each (deciphered) DTLS record.
161 * origBuf is the decrypted ssl record content and is expected to contain
162 * complete handshake records
163 * Caller must hold the handshake and RecvBuf locks.
165 * Note that this code uses msg_len for two purposes:
167 * (1) To pass the length to ssl3_HandleHandshakeMessage()
168 * (2) To carry the length of a message currently being reassembled
170 * However, unlike ssl3_HandleHandshake(), it is not used to carry
171 * the state of reassembly (i.e., whether one is in progress). That
172 * is carried in recvdHighWater and recvdFragments.
174 #define OFFSET_BYTE(o) (o/8)
175 #define OFFSET_MASK(o) (1 << (o%8))
177 SECStatus
178 dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
180 /* XXX OK for now.
181 * This doesn't work properly with asynchronous certificate validation.
182 * because that returns a WOULDBLOCK error. The current DTLS
183 * applications do not need asynchronous validation, but in the
184 * future we will need to add this.
186 sslBuffer buf = *origBuf;
187 SECStatus rv = SECSuccess;
189 PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
190 PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
192 while (buf.len > 0) {
193 PRUint8 type;
194 PRUint32 message_length;
195 PRUint16 message_seq;
196 PRUint32 fragment_offset;
197 PRUint32 fragment_length;
198 PRUint32 offset;
200 if (buf.len < 12) {
201 PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
202 rv = SECFailure;
203 break;
206 /* Parse the header */
207 type = buf.buf[0];
208 message_length = (buf.buf[1] << 16) | (buf.buf[2] << 8) | buf.buf[3];
209 message_seq = (buf.buf[4] << 8) | buf.buf[5];
210 fragment_offset = (buf.buf[6] << 16) | (buf.buf[7] << 8) | buf.buf[8];
211 fragment_length = (buf.buf[9] << 16) | (buf.buf[10] << 8) | buf.buf[11];
213 #define MAX_HANDSHAKE_MSG_LEN 0x1ffff /* 128k - 1 */
214 if (message_length > MAX_HANDSHAKE_MSG_LEN) {
215 (void)ssl3_DecodeError(ss);
216 PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
217 return SECFailure;
219 #undef MAX_HANDSHAKE_MSG_LEN
221 buf.buf += 12;
222 buf.len -= 12;
224 /* This fragment must be complete */
225 if (buf.len < fragment_length) {
226 PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
227 rv = SECFailure;
228 break;
231 /* Sanity check the packet contents */
232 if ((fragment_length + fragment_offset) > message_length) {
233 PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
234 rv = SECFailure;
235 break;
238 /* There are three ways we could not be ready for this packet.
240 * 1. It's a partial next message.
241 * 2. It's a partial or complete message beyond the next
242 * 3. It's a message we've already seen
244 * If it's the complete next message we accept it right away.
245 * This is the common case for short messages
247 if ((message_seq == ss->ssl3.hs.recvMessageSeq)
248 && (fragment_offset == 0)
249 && (fragment_length == message_length)) {
250 /* Complete next message. Process immediately */
251 ss->ssl3.hs.msg_type = (SSL3HandshakeType)type;
252 ss->ssl3.hs.msg_len = message_length;
254 /* At this point we are advancing our state machine, so
255 * we can free our last flight of messages */
256 dtls_FreeHandshakeMessages(&ss->ssl3.hs.lastMessageFlight);
257 ss->ssl3.hs.recvdHighWater = -1;
258 dtls_CancelTimer(ss);
260 /* Reset the timer to the initial value if the retry counter
261 * is 0, per Sec. 4.2.4.1 */
262 if (ss->ssl3.hs.rtRetries == 0) {
263 ss->ssl3.hs.rtTimeoutMs = INITIAL_DTLS_TIMEOUT_MS;
266 rv = ssl3_HandleHandshakeMessage(ss, buf.buf, ss->ssl3.hs.msg_len);
267 if (rv == SECFailure) {
268 /* Do not attempt to process rest of messages in this record */
269 break;
271 } else {
272 if (message_seq < ss->ssl3.hs.recvMessageSeq) {
273 /* Case 3: we do an immediate retransmit if we're
274 * in a waiting state*/
275 if (ss->ssl3.hs.rtTimerCb == NULL) {
276 /* Ignore */
277 } else if (ss->ssl3.hs.rtTimerCb ==
278 dtls_RetransmitTimerExpiredCb) {
279 SSL_TRC(30, ("%d: SSL3[%d]: Retransmit detected",
280 SSL_GETPID(), ss->fd));
281 /* Check to see if we retransmitted recently. If so,
282 * suppress the triggered retransmit. This avoids
283 * retransmit wars after packet loss.
284 * This is not in RFC 5346 but should be
286 if ((PR_IntervalNow() - ss->ssl3.hs.rtTimerStarted) >
287 (ss->ssl3.hs.rtTimeoutMs / 4)) {
288 SSL_TRC(30,
289 ("%d: SSL3[%d]: Shortcutting retransmit timer",
290 SSL_GETPID(), ss->fd));
292 /* Cancel the timer and call the CB,
293 * which re-arms the timer */
294 dtls_CancelTimer(ss);
295 dtls_RetransmitTimerExpiredCb(ss);
296 rv = SECSuccess;
297 break;
298 } else {
299 SSL_TRC(30,
300 ("%d: SSL3[%d]: We just retransmitted. Ignoring.",
301 SSL_GETPID(), ss->fd));
302 rv = SECSuccess;
303 break;
305 } else if (ss->ssl3.hs.rtTimerCb == dtls_FinishedTimerCb) {
306 /* Retransmit the messages and re-arm the timer
307 * Note that we are not backing off the timer here.
308 * The spec isn't clear and my reasoning is that this
309 * may be a re-ordered packet rather than slowness,
310 * so let's be aggressive. */
311 dtls_CancelTimer(ss);
312 rv = dtls_TransmitMessageFlight(ss);
313 if (rv == SECSuccess) {
314 rv = dtls_StartTimer(ss, dtls_FinishedTimerCb);
316 if (rv != SECSuccess)
317 return rv;
318 break;
320 } else if (message_seq > ss->ssl3.hs.recvMessageSeq) {
321 /* Case 2
323 * Ignore this message. This means we don't handle out of
324 * order complete messages that well, but we're still
325 * compliant and this probably does not happen often
327 * XXX OK for now. Maybe do something smarter at some point?
329 } else {
330 /* Case 1
332 * Buffer the fragment for reassembly
334 /* Make room for the message */
335 if (ss->ssl3.hs.recvdHighWater == -1) {
336 PRUint32 map_length = OFFSET_BYTE(message_length) + 1;
338 rv = sslBuffer_Grow(&ss->ssl3.hs.msg_body, message_length);
339 if (rv != SECSuccess)
340 break;
341 /* Make room for the fragment map */
342 rv = sslBuffer_Grow(&ss->ssl3.hs.recvdFragments,
343 map_length);
344 if (rv != SECSuccess)
345 break;
347 /* Reset the reassembly map */
348 ss->ssl3.hs.recvdHighWater = 0;
349 PORT_Memset(ss->ssl3.hs.recvdFragments.buf, 0,
350 ss->ssl3.hs.recvdFragments.space);
351 ss->ssl3.hs.msg_type = (SSL3HandshakeType)type;
352 ss->ssl3.hs.msg_len = message_length;
355 /* If we have a message length mismatch, abandon the reassembly
356 * in progress and hope that the next retransmit will give us
357 * something sane
359 if (message_length != ss->ssl3.hs.msg_len) {
360 ss->ssl3.hs.recvdHighWater = -1;
361 PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
362 rv = SECFailure;
363 break;
366 /* Now copy this fragment into the buffer */
367 PORT_Assert((fragment_offset + fragment_length) <=
368 ss->ssl3.hs.msg_body.space);
369 PORT_Memcpy(ss->ssl3.hs.msg_body.buf + fragment_offset,
370 buf.buf, fragment_length);
372 /* This logic is a bit tricky. We have two values for
373 * reassembly state:
375 * - recvdHighWater contains the highest contiguous number of
376 * bytes received
377 * - recvdFragments contains a bitmask of packets received
378 * above recvdHighWater
380 * This avoids having to fill in the bitmask in the common
381 * case of adjacent fragments received in sequence
383 if (fragment_offset <= ss->ssl3.hs.recvdHighWater) {
384 /* Either this is the adjacent fragment or an overlapping
385 * fragment */
386 ss->ssl3.hs.recvdHighWater = fragment_offset +
387 fragment_length;
388 } else {
389 for (offset = fragment_offset;
390 offset < fragment_offset + fragment_length;
391 offset++) {
392 ss->ssl3.hs.recvdFragments.buf[OFFSET_BYTE(offset)] |=
393 OFFSET_MASK(offset);
397 /* Now figure out the new high water mark if appropriate */
398 for (offset = ss->ssl3.hs.recvdHighWater;
399 offset < ss->ssl3.hs.msg_len; offset++) {
400 /* Note that this loop is not efficient, since it counts
401 * bit by bit. If we have a lot of out-of-order packets,
402 * we should optimize this */
403 if (ss->ssl3.hs.recvdFragments.buf[OFFSET_BYTE(offset)] &
404 OFFSET_MASK(offset)) {
405 ss->ssl3.hs.recvdHighWater++;
406 } else {
407 break;
411 /* If we have all the bytes, then we are good to go */
412 if (ss->ssl3.hs.recvdHighWater == ss->ssl3.hs.msg_len) {
413 ss->ssl3.hs.recvdHighWater = -1;
415 rv = ssl3_HandleHandshakeMessage(ss,
416 ss->ssl3.hs.msg_body.buf,
417 ss->ssl3.hs.msg_len);
418 if (rv == SECFailure)
419 break; /* Skip rest of record */
421 /* At this point we are advancing our state machine, so
422 * we can free our last flight of messages */
423 dtls_FreeHandshakeMessages(&ss->ssl3.hs.lastMessageFlight);
424 dtls_CancelTimer(ss);
426 /* If there have been no retries this time, reset the
427 * timer value to the default per Section 4.2.4.1 */
428 if (ss->ssl3.hs.rtRetries == 0) {
429 ss->ssl3.hs.rtTimeoutMs = INITIAL_DTLS_TIMEOUT_MS;
435 buf.buf += fragment_length;
436 buf.len -= fragment_length;
439 origBuf->len = 0; /* So ssl3_GatherAppDataRecord will keep looping. */
441 /* XXX OK for now. In future handle rv == SECWouldBlock safely in order
442 * to deal with asynchronous certificate verification */
443 return rv;
446 /* Enqueue a message (either handshake or CCS)
448 * Called from:
449 * dtls_StageHandshakeMessage()
450 * ssl3_SendChangeCipherSpecs()
452 SECStatus dtls_QueueMessage(sslSocket *ss, SSL3ContentType type,
453 const SSL3Opaque *pIn, PRInt32 nIn)
455 SECStatus rv = SECSuccess;
456 DTLSQueuedMessage *msg = NULL;
458 PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
459 PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
461 msg = dtls_AllocQueuedMessage(ss->ssl3.cwSpec->epoch, type, pIn, nIn);
463 if (!msg) {
464 PORT_SetError(SEC_ERROR_NO_MEMORY);
465 rv = SECFailure;
466 } else {
467 PR_APPEND_LINK(&msg->link, &ss->ssl3.hs.lastMessageFlight);
470 return rv;
473 /* Add DTLS handshake message to the pending queue
474 * Empty the sendBuf buffer.
475 * This function returns SECSuccess or SECFailure, never SECWouldBlock.
476 * Always set sendBuf.len to 0, even when returning SECFailure.
478 * Called from:
479 * ssl3_AppendHandshakeHeader()
480 * dtls_FlushHandshake()
482 SECStatus
483 dtls_StageHandshakeMessage(sslSocket *ss)
485 SECStatus rv = SECSuccess;
487 PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
488 PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
490 /* This function is sometimes called when no data is actually to
491 * be staged, so just return SECSuccess. */
492 if (!ss->sec.ci.sendBuf.buf || !ss->sec.ci.sendBuf.len)
493 return rv;
495 rv = dtls_QueueMessage(ss, content_handshake,
496 ss->sec.ci.sendBuf.buf, ss->sec.ci.sendBuf.len);
498 /* Whether we succeeded or failed, toss the old handshake data. */
499 ss->sec.ci.sendBuf.len = 0;
500 return rv;
503 /* Enqueue the handshake message in sendBuf (if any) and then
504 * transmit the resulting flight of handshake messages.
506 * Called from:
507 * ssl3_FlushHandshake()
509 SECStatus
510 dtls_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags)
512 SECStatus rv = SECSuccess;
514 PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
515 PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
517 rv = dtls_StageHandshakeMessage(ss);
518 if (rv != SECSuccess)
519 return rv;
521 if (!(flags & ssl_SEND_FLAG_FORCE_INTO_BUFFER)) {
522 rv = dtls_TransmitMessageFlight(ss);
523 if (rv != SECSuccess)
524 return rv;
526 if (!(flags & ssl_SEND_FLAG_NO_RETRANSMIT)) {
527 ss->ssl3.hs.rtRetries = 0;
528 rv = dtls_StartTimer(ss, dtls_RetransmitTimerExpiredCb);
532 return rv;
535 /* The callback for when the retransmit timer expires
537 * Called from:
538 * dtls_CheckTimer()
539 * dtls_HandleHandshake()
541 static void
542 dtls_RetransmitTimerExpiredCb(sslSocket *ss)
544 SECStatus rv = SECFailure;
546 ss->ssl3.hs.rtRetries++;
548 if (!(ss->ssl3.hs.rtRetries % 3)) {
549 /* If one of the messages was potentially greater than > MTU,
550 * then downgrade. Do this every time we have retransmitted a
551 * message twice, per RFC 6347 Sec. 4.1.1 */
552 dtls_SetMTU(ss, ss->ssl3.hs.maxMessageSent - 1);
555 rv = dtls_TransmitMessageFlight(ss);
556 if (rv == SECSuccess) {
558 /* Re-arm the timer */
559 rv = dtls_RestartTimer(ss, PR_TRUE, dtls_RetransmitTimerExpiredCb);
562 if (rv == SECFailure) {
563 /* XXX OK for now. In future maybe signal the stack that we couldn't
564 * transmit. For now, let the read handle any real network errors */
568 /* Transmit a flight of handshake messages, stuffing them
569 * into as few records as seems reasonable
571 * Called from:
572 * dtls_FlushHandshake()
573 * dtls_RetransmitTimerExpiredCb()
575 static SECStatus
576 dtls_TransmitMessageFlight(sslSocket *ss)
578 SECStatus rv = SECSuccess;
579 PRCList *msg_p;
580 PRUint16 room_left = ss->ssl3.mtu;
581 PRInt32 sent;
583 ssl_GetXmitBufLock(ss);
584 ssl_GetSpecReadLock(ss);
586 /* DTLS does not buffer its handshake messages in
587 * ss->pendingBuf, but rather in the lastMessageFlight
588 * structure. This is just a sanity check that
589 * some programming error hasn't inadvertantly
590 * stuffed something in ss->pendingBuf
592 PORT_Assert(!ss->pendingBuf.len);
593 for (msg_p = PR_LIST_HEAD(&ss->ssl3.hs.lastMessageFlight);
594 msg_p != &ss->ssl3.hs.lastMessageFlight;
595 msg_p = PR_NEXT_LINK(msg_p)) {
596 DTLSQueuedMessage *msg = (DTLSQueuedMessage *)msg_p;
598 /* The logic here is:
600 * 1. If this is a message that will not fit into the remaining
601 * space, then flush.
602 * 2. If the message will now fit into the remaining space,
603 * encrypt, buffer, and loop.
604 * 3. If the message will not fit, then fragment.
606 * At the end of the function, flush.
608 if ((msg->len + SSL3_BUFFER_FUDGE) > room_left) {
609 /* The message will not fit into the remaining space, so flush */
610 rv = dtls_SendSavedWriteData(ss);
611 if (rv != SECSuccess)
612 break;
614 room_left = ss->ssl3.mtu;
617 if ((msg->len + SSL3_BUFFER_FUDGE) <= room_left) {
618 /* The message will fit, so encrypt and then continue with the
619 * next packet */
620 sent = ssl3_SendRecord(ss, msg->epoch, msg->type,
621 msg->data, msg->len,
622 ssl_SEND_FLAG_FORCE_INTO_BUFFER |
623 ssl_SEND_FLAG_USE_EPOCH);
624 if (sent != msg->len) {
625 rv = SECFailure;
626 if (sent != -1) {
627 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
629 break;
632 room_left = ss->ssl3.mtu - ss->pendingBuf.len;
633 } else {
634 /* The message will not fit, so fragment.
636 * XXX OK for now. Arrange to coalesce the last fragment
637 * of this message with the next message if possible.
638 * That would be more efficient.
640 PRUint32 fragment_offset = 0;
641 unsigned char fragment[DTLS_MAX_MTU]; /* >= than largest
642 * plausible MTU */
644 /* Assert that we have already flushed */
645 PORT_Assert(room_left == ss->ssl3.mtu);
647 /* Case 3: We now need to fragment this message
648 * DTLS only supports fragmenting handshaking messages */
649 PORT_Assert(msg->type == content_handshake);
651 /* The headers consume 12 bytes so the smalles possible
652 * message (i.e., an empty one) is 12 bytes
654 PORT_Assert(msg->len >= 12);
656 while ((fragment_offset + 12) < msg->len) {
657 PRUint32 fragment_len;
658 const unsigned char *content = msg->data + 12;
659 PRUint32 content_len = msg->len - 12;
661 /* The reason we use 8 here is that that's the length of
662 * the new DTLS data that we add to the header */
663 fragment_len = PR_MIN(room_left - (SSL3_BUFFER_FUDGE + 8),
664 content_len - fragment_offset);
665 PORT_Assert(fragment_len < DTLS_MAX_MTU - 12);
666 /* Make totally sure that we are within the buffer.
667 * Note that the only way that fragment len could get
668 * adjusted here is if
670 * (a) we are in release mode so the PORT_Assert is compiled out
671 * (b) either the MTU table is inconsistent with DTLS_MAX_MTU
672 * or ss->ssl3.mtu has become corrupt.
674 fragment_len = PR_MIN(fragment_len, DTLS_MAX_MTU - 12);
676 /* Construct an appropriate-sized fragment */
677 /* Type, length, sequence */
678 PORT_Memcpy(fragment, msg->data, 6);
680 /* Offset */
681 fragment[6] = (fragment_offset >> 16) & 0xff;
682 fragment[7] = (fragment_offset >> 8) & 0xff;
683 fragment[8] = (fragment_offset) & 0xff;
685 /* Fragment length */
686 fragment[9] = (fragment_len >> 16) & 0xff;
687 fragment[10] = (fragment_len >> 8) & 0xff;
688 fragment[11] = (fragment_len) & 0xff;
690 PORT_Memcpy(fragment + 12, content + fragment_offset,
691 fragment_len);
694 * Send the record. We do this in two stages
695 * 1. Encrypt
697 sent = ssl3_SendRecord(ss, msg->epoch, msg->type,
698 fragment, fragment_len + 12,
699 ssl_SEND_FLAG_FORCE_INTO_BUFFER |
700 ssl_SEND_FLAG_USE_EPOCH);
701 if (sent != (fragment_len + 12)) {
702 rv = SECFailure;
703 if (sent != -1) {
704 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
706 break;
709 /* 2. Flush */
710 rv = dtls_SendSavedWriteData(ss);
711 if (rv != SECSuccess)
712 break;
714 fragment_offset += fragment_len;
719 /* Finally, we need to flush */
720 if (rv == SECSuccess)
721 rv = dtls_SendSavedWriteData(ss);
723 /* Give up the locks */
724 ssl_ReleaseSpecReadLock(ss);
725 ssl_ReleaseXmitBufLock(ss);
727 return rv;
730 /* Flush the data in the pendingBuf and update the max message sent
731 * so we can adjust the MTU estimate if we need to.
732 * Wrapper for ssl_SendSavedWriteData.
734 * Called from dtls_TransmitMessageFlight()
736 static
737 SECStatus dtls_SendSavedWriteData(sslSocket *ss)
739 PRInt32 sent;
741 sent = ssl_SendSavedWriteData(ss);
742 if (sent < 0)
743 return SECFailure;
745 /* We should always have complete writes b/c datagram sockets
746 * don't really block */
747 if (ss->pendingBuf.len > 0) {
748 ssl_MapLowLevelError(SSL_ERROR_SOCKET_WRITE_FAILURE);
749 return SECFailure;
752 /* Update the largest message sent so we can adjust the MTU
753 * estimate if necessary */
754 if (sent > ss->ssl3.hs.maxMessageSent)
755 ss->ssl3.hs.maxMessageSent = sent;
757 return SECSuccess;
760 /* Compress, MAC, encrypt a DTLS record. Allows specification of
761 * the epoch using epoch value. If use_epoch is PR_TRUE then
762 * we use the provided epoch. If use_epoch is PR_FALSE then
763 * whatever the current value is in effect is used.
765 * Called from ssl3_SendRecord()
767 SECStatus
768 dtls_CompressMACEncryptRecord(sslSocket * ss,
769 DTLSEpoch epoch,
770 PRBool use_epoch,
771 SSL3ContentType type,
772 const SSL3Opaque * pIn,
773 PRUint32 contentLen,
774 sslBuffer * wrBuf)
776 SECStatus rv = SECFailure;
777 ssl3CipherSpec * cwSpec;
779 ssl_GetSpecReadLock(ss); /********************************/
781 /* The reason for this switch-hitting code is that we might have
782 * a flight of records spanning an epoch boundary, e.g.,
784 * ClientKeyExchange (epoch = 0)
785 * ChangeCipherSpec (epoch = 0)
786 * Finished (epoch = 1)
788 * Thus, each record needs a different cipher spec. The information
789 * about which epoch to use is carried with the record.
791 if (use_epoch) {
792 if (ss->ssl3.cwSpec->epoch == epoch)
793 cwSpec = ss->ssl3.cwSpec;
794 else if (ss->ssl3.pwSpec->epoch == epoch)
795 cwSpec = ss->ssl3.pwSpec;
796 else
797 cwSpec = NULL;
798 } else {
799 cwSpec = ss->ssl3.cwSpec;
802 if (cwSpec) {
803 rv = ssl3_CompressMACEncryptRecord(cwSpec, ss->sec.isServer, PR_TRUE,
804 PR_FALSE, type, pIn, contentLen,
805 wrBuf);
806 } else {
807 PR_NOT_REACHED("Couldn't find a cipher spec matching epoch");
808 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
810 ssl_ReleaseSpecReadLock(ss); /************************************/
812 return rv;
815 /* Start a timer
817 * Called from:
818 * dtls_HandleHandshake()
819 * dtls_FlushHAndshake()
820 * dtls_RestartTimer()
822 SECStatus
823 dtls_StartTimer(sslSocket *ss, DTLSTimerCb cb)
825 PORT_Assert(ss->ssl3.hs.rtTimerCb == NULL);
827 ss->ssl3.hs.rtTimerStarted = PR_IntervalNow();
828 ss->ssl3.hs.rtTimerCb = cb;
830 return SECSuccess;
833 /* Restart a timer with optional backoff
835 * Called from dtls_RetransmitTimerExpiredCb()
837 SECStatus
838 dtls_RestartTimer(sslSocket *ss, PRBool backoff, DTLSTimerCb cb)
840 if (backoff) {
841 ss->ssl3.hs.rtTimeoutMs *= 2;
842 if (ss->ssl3.hs.rtTimeoutMs > MAX_DTLS_TIMEOUT_MS)
843 ss->ssl3.hs.rtTimeoutMs = MAX_DTLS_TIMEOUT_MS;
846 return dtls_StartTimer(ss, cb);
849 /* Cancel a pending timer
851 * Called from:
852 * dtls_HandleHandshake()
853 * dtls_CheckTimer()
855 void
856 dtls_CancelTimer(sslSocket *ss)
858 PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
860 ss->ssl3.hs.rtTimerCb = NULL;
863 /* Check the pending timer and fire the callback if it expired
865 * Called from ssl3_GatherCompleteHandshake()
867 void
868 dtls_CheckTimer(sslSocket *ss)
870 if (!ss->ssl3.hs.rtTimerCb)
871 return;
873 if ((PR_IntervalNow() - ss->ssl3.hs.rtTimerStarted) >
874 PR_MillisecondsToInterval(ss->ssl3.hs.rtTimeoutMs)) {
875 /* Timer has expired */
876 DTLSTimerCb cb = ss->ssl3.hs.rtTimerCb;
878 /* Cancel the timer so that we can call the CB safely */
879 dtls_CancelTimer(ss);
881 /* Now call the CB */
882 cb(ss);
886 /* The callback to fire when the holddown timer for the Finished
887 * message expires and we can delete it
889 * Called from dtls_CheckTimer()
891 void
892 dtls_FinishedTimerCb(sslSocket *ss)
894 ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_FALSE);
897 /* Cancel the Finished hold-down timer and destroy the
898 * pending cipher spec. Note that this means that
899 * successive rehandshakes will fail if the Finished is
900 * lost.
902 * XXX OK for now. Figure out how to handle the combination
903 * of Finished lost and rehandshake
905 void
906 dtls_RehandshakeCleanup(sslSocket *ss)
908 dtls_CancelTimer(ss);
909 ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_FALSE);
910 ss->ssl3.hs.sendMessageSeq = 0;
911 ss->ssl3.hs.recvMessageSeq = 0;
914 /* Set the MTU to the next step less than or equal to the
915 * advertised value. Also used to downgrade the MTU by
916 * doing dtls_SetMTU(ss, biggest packet set).
918 * Passing 0 means set this to the largest MTU known
919 * (effectively resetting the PMTU backoff value).
921 * Called by:
922 * ssl3_InitState()
923 * dtls_RetransmitTimerExpiredCb()
925 void
926 dtls_SetMTU(sslSocket *ss, PRUint16 advertised)
928 int i;
930 if (advertised == 0) {
931 ss->ssl3.mtu = COMMON_MTU_VALUES[0];
932 SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
933 return;
936 for (i = 0; i < PR_ARRAY_SIZE(COMMON_MTU_VALUES); i++) {
937 if (COMMON_MTU_VALUES[i] <= advertised) {
938 ss->ssl3.mtu = COMMON_MTU_VALUES[i];
939 SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
940 return;
944 /* Fallback */
945 ss->ssl3.mtu = COMMON_MTU_VALUES[PR_ARRAY_SIZE(COMMON_MTU_VALUES)-1];
946 SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
949 /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a
950 * DTLS hello_verify_request
951 * Caller must hold Handshake and RecvBuf locks.
953 SECStatus
954 dtls_HandleHelloVerifyRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
956 int errCode = SSL_ERROR_RX_MALFORMED_HELLO_VERIFY_REQUEST;
957 SECStatus rv;
958 PRInt32 temp;
959 SECItem cookie = {siBuffer, NULL, 0};
960 SSL3AlertDescription desc = illegal_parameter;
962 SSL_TRC(3, ("%d: SSL3[%d]: handle hello_verify_request handshake",
963 SSL_GETPID(), ss->fd));
964 PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
965 PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
967 if (ss->ssl3.hs.ws != wait_server_hello) {
968 errCode = SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST;
969 desc = unexpected_message;
970 goto alert_loser;
973 /* The version */
974 temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
975 if (temp < 0) {
976 goto loser; /* alert has been sent */
979 if (temp != SSL_LIBRARY_VERSION_DTLS_1_0_WIRE) {
980 /* Note: this will need adjustment for DTLS 1.2 per Section 4.2.1 */
981 goto alert_loser;
984 /* The cookie */
985 rv = ssl3_ConsumeHandshakeVariable(ss, &cookie, 1, &b, &length);
986 if (rv != SECSuccess) {
987 goto loser; /* alert has been sent */
989 if (cookie.len > DTLS_COOKIE_BYTES) {
990 desc = decode_error;
991 goto alert_loser; /* malformed. */
994 PORT_Memcpy(ss->ssl3.hs.cookie, cookie.data, cookie.len);
995 ss->ssl3.hs.cookieLen = cookie.len;
998 ssl_GetXmitBufLock(ss); /*******************************/
1000 /* Now re-send the client hello */
1001 rv = ssl3_SendClientHello(ss, PR_TRUE);
1003 ssl_ReleaseXmitBufLock(ss); /*******************************/
1005 if (rv == SECSuccess)
1006 return rv;
1008 alert_loser:
1009 (void)SSL3_SendAlert(ss, alert_fatal, desc);
1011 loser:
1012 errCode = ssl_MapLowLevelError(errCode);
1013 return SECFailure;
1016 /* Initialize the DTLS anti-replay window
1018 * Called from:
1019 * ssl3_SetupPendingCipherSpec()
1020 * ssl3_InitCipherSpec()
1022 void
1023 dtls_InitRecvdRecords(DTLSRecvdRecords *records)
1025 PORT_Memset(records->data, 0, sizeof(records->data));
1026 records->left = 0;
1027 records->right = DTLS_RECVD_RECORDS_WINDOW - 1;
1031 * Has this DTLS record been received? Return values are:
1032 * -1 -- out of range to the left
1033 * 0 -- not received yet
1034 * 1 -- replay
1036 * Called from: dtls_HandleRecord()
1039 dtls_RecordGetRecvd(DTLSRecvdRecords *records, PRUint64 seq)
1041 PRUint64 offset;
1043 /* Out of range to the left */
1044 if (seq < records->left) {
1045 return -1;
1048 /* Out of range to the right; since we advance the window on
1049 * receipt, that means that this packet has not been received
1050 * yet */
1051 if (seq > records->right)
1052 return 0;
1054 offset = seq % DTLS_RECVD_RECORDS_WINDOW;
1056 return !!(records->data[offset / 8] & (1 << (offset % 8)));
1059 /* Update the DTLS anti-replay window
1061 * Called from ssl3_HandleRecord()
1063 void
1064 dtls_RecordSetRecvd(DTLSRecvdRecords *records, PRUint64 seq)
1066 PRUint64 offset;
1068 if (seq < records->left)
1069 return;
1071 if (seq > records->right) {
1072 PRUint64 new_left;
1073 PRUint64 new_right;
1074 PRUint64 right;
1076 /* Slide to the right; this is the tricky part
1078 * 1. new_top is set to have room for seq, on the
1079 * next byte boundary by setting the right 8
1080 * bits of seq
1081 * 2. new_left is set to compensate.
1082 * 3. Zero all bits between top and new_top. Since
1083 * this is a ring, this zeroes everything as-yet
1084 * unseen. Because we always operate on byte
1085 * boundaries, we can zero one byte at a time
1087 new_right = seq | 0x07;
1088 new_left = (new_right - DTLS_RECVD_RECORDS_WINDOW) + 1;
1090 for (right = records->right + 8; right <= new_right; right += 8) {
1091 offset = right % DTLS_RECVD_RECORDS_WINDOW;
1092 records->data[offset / 8] = 0;
1095 records->right = new_right;
1096 records->left = new_left;
1099 offset = seq % DTLS_RECVD_RECORDS_WINDOW;
1101 records->data[offset / 8] |= (1 << (offset % 8));
1104 SECStatus
1105 DTLS_GetHandshakeTimeout(PRFileDesc *socket, PRIntervalTime *timeout)
1107 sslSocket * ss = NULL;
1108 PRIntervalTime elapsed;
1109 PRIntervalTime desired;
1111 ss = ssl_FindSocket(socket);
1113 if (!ss)
1114 return SECFailure;
1116 if (!IS_DTLS(ss))
1117 return SECFailure;
1119 if (!ss->ssl3.hs.rtTimerCb)
1120 return SECFailure;
1122 elapsed = PR_IntervalNow() - ss->ssl3.hs.rtTimerStarted;
1123 desired = PR_MillisecondsToInterval(ss->ssl3.hs.rtTimeoutMs);
1124 if (elapsed > desired) {
1125 /* Timer expired */
1126 *timeout = PR_INTERVAL_NO_WAIT;
1127 } else {
1128 *timeout = desired - elapsed;
1131 return SECSuccess;