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/. */
14 #define PR_ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
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 #ifndef NSS_DISABLE_ECC
34 TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
,
35 TLS_ECDHE_RSA_WITH_RC4_128_SHA
,
36 #endif /* NSS_DISABLE_ECC */
37 TLS_DHE_DSS_WITH_RC4_128_SHA
,
38 #ifndef NSS_DISABLE_ECC
39 TLS_ECDH_RSA_WITH_RC4_128_SHA
,
40 TLS_ECDH_ECDSA_WITH_RC4_128_SHA
,
41 #endif /* NSS_DISABLE_ECC */
42 TLS_RSA_WITH_RC4_128_MD5
,
43 TLS_RSA_WITH_RC4_128_SHA
,
44 TLS_RSA_EXPORT1024_WITH_RC4_56_SHA
,
45 TLS_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.
53 * 1.1 (0302) 1.0 (feff)
54 * 1.2 (0303) 1.2 (fefd)
55 * 1.3 (0304) 1.3 (fefc)
58 dtls_TLSVersionToDTLSVersion(SSL3ProtocolVersion tlsv
)
60 if (tlsv
== SSL_LIBRARY_VERSION_TLS_1_1
) {
61 return SSL_LIBRARY_VERSION_DTLS_1_0_WIRE
;
63 if (tlsv
== SSL_LIBRARY_VERSION_TLS_1_2
) {
64 return SSL_LIBRARY_VERSION_DTLS_1_2_WIRE
;
66 if (tlsv
== SSL_LIBRARY_VERSION_TLS_1_3
) {
67 return SSL_LIBRARY_VERSION_DTLS_1_3_WIRE
;
70 /* Anything other than TLS 1.1 or 1.2 is an error, so return
71 * the invalid version 0xffff. */
75 /* Map known DTLS versions to known TLS versions.
76 * - Invalid versions (< 1.0) return a version of 0
77 * - Versions > known return a version one higher than we know of
78 * to accomodate a theoretically newer version */
80 dtls_DTLSVersionToTLSVersion(SSL3ProtocolVersion dtlsv
)
82 if (MSB(dtlsv
) == 0xff) {
86 if (dtlsv
== SSL_LIBRARY_VERSION_DTLS_1_0_WIRE
) {
87 return SSL_LIBRARY_VERSION_TLS_1_1
;
89 if (dtlsv
== SSL_LIBRARY_VERSION_DTLS_1_2_WIRE
) {
90 return SSL_LIBRARY_VERSION_TLS_1_2
;
92 if (dtlsv
== SSL_LIBRARY_VERSION_DTLS_1_3_WIRE
) {
93 return SSL_LIBRARY_VERSION_TLS_1_3
;
96 /* Return a fictional higher version than we know of */
97 return SSL_LIBRARY_VERSION_TLS_1_2
+ 1;
100 /* On this socket, Disable non-DTLS cipher suites in the argument's list */
102 ssl3_DisableNonDTLSSuites(sslSocket
* ss
)
104 const ssl3CipherSuite
* suite
;
106 for (suite
= nonDTLSSuites
; *suite
; ++suite
) {
107 SECStatus rv
= ssl3_CipherPrefSet(ss
, *suite
, PR_FALSE
);
109 PORT_Assert(rv
== SECSuccess
); /* else is coding error */
114 /* Allocate a DTLSQueuedMessage.
116 * Called from dtls_QueueMessage()
118 static DTLSQueuedMessage
*
119 dtls_AllocQueuedMessage(PRUint16 epoch
, SSL3ContentType type
,
120 const unsigned char *data
, PRUint32 len
)
122 DTLSQueuedMessage
*msg
= NULL
;
124 msg
= PORT_ZAlloc(sizeof(DTLSQueuedMessage
));
128 msg
->data
= PORT_Alloc(len
);
133 PORT_Memcpy(msg
->data
, data
, len
);
143 * Free a handshake message
145 * Called from dtls_FreeHandshakeMessages()
148 dtls_FreeHandshakeMessage(DTLSQueuedMessage
*msg
)
153 PORT_ZFree(msg
->data
, msg
->len
);
158 * Free a list of handshake messages
161 * dtls_HandleHandshake()
162 * ssl3_DestroySSL3Info()
165 dtls_FreeHandshakeMessages(PRCList
*list
)
169 while (!PR_CLIST_IS_EMPTY(list
)) {
170 cur_p
= PR_LIST_TAIL(list
);
171 PR_REMOVE_LINK(cur_p
);
172 dtls_FreeHandshakeMessage((DTLSQueuedMessage
*)cur_p
);
176 /* Called only from ssl3_HandleRecord, for each (deciphered) DTLS record.
177 * origBuf is the decrypted ssl record content and is expected to contain
178 * complete handshake records
179 * Caller must hold the handshake and RecvBuf locks.
181 * Note that this code uses msg_len for two purposes:
183 * (1) To pass the length to ssl3_HandleHandshakeMessage()
184 * (2) To carry the length of a message currently being reassembled
186 * However, unlike ssl3_HandleHandshake(), it is not used to carry
187 * the state of reassembly (i.e., whether one is in progress). That
188 * is carried in recvdHighWater and recvdFragments.
190 #define OFFSET_BYTE(o) (o/8)
191 #define OFFSET_MASK(o) (1 << (o%8))
194 dtls_HandleHandshake(sslSocket
*ss
, sslBuffer
*origBuf
)
197 * This doesn't work properly with asynchronous certificate validation.
198 * because that returns a WOULDBLOCK error. The current DTLS
199 * applications do not need asynchronous validation, but in the
200 * future we will need to add this.
202 sslBuffer buf
= *origBuf
;
203 SECStatus rv
= SECSuccess
;
205 PORT_Assert(ss
->opt
.noLocks
|| ssl_HaveRecvBufLock(ss
));
206 PORT_Assert(ss
->opt
.noLocks
|| ssl_HaveSSL3HandshakeLock(ss
));
208 while (buf
.len
> 0) {
210 PRUint32 message_length
;
211 PRUint16 message_seq
;
212 PRUint32 fragment_offset
;
213 PRUint32 fragment_length
;
217 PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE
);
222 /* Parse the header */
224 message_length
= (buf
.buf
[1] << 16) | (buf
.buf
[2] << 8) | buf
.buf
[3];
225 message_seq
= (buf
.buf
[4] << 8) | buf
.buf
[5];
226 fragment_offset
= (buf
.buf
[6] << 16) | (buf
.buf
[7] << 8) | buf
.buf
[8];
227 fragment_length
= (buf
.buf
[9] << 16) | (buf
.buf
[10] << 8) | buf
.buf
[11];
229 #define MAX_HANDSHAKE_MSG_LEN 0x1ffff /* 128k - 1 */
230 if (message_length
> MAX_HANDSHAKE_MSG_LEN
) {
231 (void)ssl3_DecodeError(ss
);
232 PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG
);
235 #undef MAX_HANDSHAKE_MSG_LEN
240 /* This fragment must be complete */
241 if (buf
.len
< fragment_length
) {
242 PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE
);
247 /* Sanity check the packet contents */
248 if ((fragment_length
+ fragment_offset
) > message_length
) {
249 PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE
);
254 /* There are three ways we could not be ready for this packet.
256 * 1. It's a partial next message.
257 * 2. It's a partial or complete message beyond the next
258 * 3. It's a message we've already seen
260 * If it's the complete next message we accept it right away.
261 * This is the common case for short messages
263 if ((message_seq
== ss
->ssl3
.hs
.recvMessageSeq
)
264 && (fragment_offset
== 0)
265 && (fragment_length
== message_length
)) {
266 /* Complete next message. Process immediately */
267 ss
->ssl3
.hs
.msg_type
= (SSL3HandshakeType
)type
;
268 ss
->ssl3
.hs
.msg_len
= message_length
;
270 /* At this point we are advancing our state machine, so
271 * we can free our last flight of messages */
272 dtls_FreeHandshakeMessages(&ss
->ssl3
.hs
.lastMessageFlight
);
273 ss
->ssl3
.hs
.recvdHighWater
= -1;
274 dtls_CancelTimer(ss
);
276 /* Reset the timer to the initial value if the retry counter
277 * is 0, per Sec. 4.2.4.1 */
278 if (ss
->ssl3
.hs
.rtRetries
== 0) {
279 ss
->ssl3
.hs
.rtTimeoutMs
= INITIAL_DTLS_TIMEOUT_MS
;
282 rv
= ssl3_HandleHandshakeMessage(ss
, buf
.buf
, ss
->ssl3
.hs
.msg_len
);
283 if (rv
== SECFailure
) {
284 /* Do not attempt to process rest of messages in this record */
288 if (message_seq
< ss
->ssl3
.hs
.recvMessageSeq
) {
289 /* Case 3: we do an immediate retransmit if we're
290 * in a waiting state*/
291 if (ss
->ssl3
.hs
.rtTimerCb
== NULL
) {
293 } else if (ss
->ssl3
.hs
.rtTimerCb
==
294 dtls_RetransmitTimerExpiredCb
) {
295 SSL_TRC(30, ("%d: SSL3[%d]: Retransmit detected",
296 SSL_GETPID(), ss
->fd
));
297 /* Check to see if we retransmitted recently. If so,
298 * suppress the triggered retransmit. This avoids
299 * retransmit wars after packet loss.
300 * This is not in RFC 5346 but should be
302 if ((PR_IntervalNow() - ss
->ssl3
.hs
.rtTimerStarted
) >
303 (ss
->ssl3
.hs
.rtTimeoutMs
/ 4)) {
305 ("%d: SSL3[%d]: Shortcutting retransmit timer",
306 SSL_GETPID(), ss
->fd
));
308 /* Cancel the timer and call the CB,
309 * which re-arms the timer */
310 dtls_CancelTimer(ss
);
311 dtls_RetransmitTimerExpiredCb(ss
);
316 ("%d: SSL3[%d]: We just retransmitted. Ignoring.",
317 SSL_GETPID(), ss
->fd
));
321 } else if (ss
->ssl3
.hs
.rtTimerCb
== dtls_FinishedTimerCb
) {
322 /* Retransmit the messages and re-arm the timer
323 * Note that we are not backing off the timer here.
324 * The spec isn't clear and my reasoning is that this
325 * may be a re-ordered packet rather than slowness,
326 * so let's be aggressive. */
327 dtls_CancelTimer(ss
);
328 rv
= dtls_TransmitMessageFlight(ss
);
329 if (rv
== SECSuccess
) {
330 rv
= dtls_StartTimer(ss
, dtls_FinishedTimerCb
);
332 if (rv
!= SECSuccess
)
336 } else if (message_seq
> ss
->ssl3
.hs
.recvMessageSeq
) {
339 * Ignore this message. This means we don't handle out of
340 * order complete messages that well, but we're still
341 * compliant and this probably does not happen often
343 * XXX OK for now. Maybe do something smarter at some point?
348 * Buffer the fragment for reassembly
350 /* Make room for the message */
351 if (ss
->ssl3
.hs
.recvdHighWater
== -1) {
352 PRUint32 map_length
= OFFSET_BYTE(message_length
) + 1;
354 rv
= sslBuffer_Grow(&ss
->ssl3
.hs
.msg_body
, message_length
);
355 if (rv
!= SECSuccess
)
357 /* Make room for the fragment map */
358 rv
= sslBuffer_Grow(&ss
->ssl3
.hs
.recvdFragments
,
360 if (rv
!= SECSuccess
)
363 /* Reset the reassembly map */
364 ss
->ssl3
.hs
.recvdHighWater
= 0;
365 PORT_Memset(ss
->ssl3
.hs
.recvdFragments
.buf
, 0,
366 ss
->ssl3
.hs
.recvdFragments
.space
);
367 ss
->ssl3
.hs
.msg_type
= (SSL3HandshakeType
)type
;
368 ss
->ssl3
.hs
.msg_len
= message_length
;
371 /* If we have a message length mismatch, abandon the reassembly
372 * in progress and hope that the next retransmit will give us
375 if (message_length
!= ss
->ssl3
.hs
.msg_len
) {
376 ss
->ssl3
.hs
.recvdHighWater
= -1;
377 PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE
);
382 /* Now copy this fragment into the buffer */
383 PORT_Assert((fragment_offset
+ fragment_length
) <=
384 ss
->ssl3
.hs
.msg_body
.space
);
385 PORT_Memcpy(ss
->ssl3
.hs
.msg_body
.buf
+ fragment_offset
,
386 buf
.buf
, fragment_length
);
388 /* This logic is a bit tricky. We have two values for
391 * - recvdHighWater contains the highest contiguous number of
393 * - recvdFragments contains a bitmask of packets received
394 * above recvdHighWater
396 * This avoids having to fill in the bitmask in the common
397 * case of adjacent fragments received in sequence
399 if (fragment_offset
<= ss
->ssl3
.hs
.recvdHighWater
) {
400 /* Either this is the adjacent fragment or an overlapping
402 ss
->ssl3
.hs
.recvdHighWater
= fragment_offset
+
405 for (offset
= fragment_offset
;
406 offset
< fragment_offset
+ fragment_length
;
408 ss
->ssl3
.hs
.recvdFragments
.buf
[OFFSET_BYTE(offset
)] |=
413 /* Now figure out the new high water mark if appropriate */
414 for (offset
= ss
->ssl3
.hs
.recvdHighWater
;
415 offset
< ss
->ssl3
.hs
.msg_len
; offset
++) {
416 /* Note that this loop is not efficient, since it counts
417 * bit by bit. If we have a lot of out-of-order packets,
418 * we should optimize this */
419 if (ss
->ssl3
.hs
.recvdFragments
.buf
[OFFSET_BYTE(offset
)] &
420 OFFSET_MASK(offset
)) {
421 ss
->ssl3
.hs
.recvdHighWater
++;
427 /* If we have all the bytes, then we are good to go */
428 if (ss
->ssl3
.hs
.recvdHighWater
== ss
->ssl3
.hs
.msg_len
) {
429 ss
->ssl3
.hs
.recvdHighWater
= -1;
431 rv
= ssl3_HandleHandshakeMessage(ss
,
432 ss
->ssl3
.hs
.msg_body
.buf
,
433 ss
->ssl3
.hs
.msg_len
);
434 if (rv
== SECFailure
)
435 break; /* Skip rest of record */
437 /* At this point we are advancing our state machine, so
438 * we can free our last flight of messages */
439 dtls_FreeHandshakeMessages(&ss
->ssl3
.hs
.lastMessageFlight
);
440 dtls_CancelTimer(ss
);
442 /* If there have been no retries this time, reset the
443 * timer value to the default per Section 4.2.4.1 */
444 if (ss
->ssl3
.hs
.rtRetries
== 0) {
445 ss
->ssl3
.hs
.rtTimeoutMs
= INITIAL_DTLS_TIMEOUT_MS
;
451 buf
.buf
+= fragment_length
;
452 buf
.len
-= fragment_length
;
455 origBuf
->len
= 0; /* So ssl3_GatherAppDataRecord will keep looping. */
457 /* XXX OK for now. In future handle rv == SECWouldBlock safely in order
458 * to deal with asynchronous certificate verification */
462 /* Enqueue a message (either handshake or CCS)
465 * dtls_StageHandshakeMessage()
466 * ssl3_SendChangeCipherSpecs()
468 SECStatus
dtls_QueueMessage(sslSocket
*ss
, SSL3ContentType type
,
469 const SSL3Opaque
*pIn
, PRInt32 nIn
)
471 SECStatus rv
= SECSuccess
;
472 DTLSQueuedMessage
*msg
= NULL
;
474 PORT_Assert(ss
->opt
.noLocks
|| ssl_HaveSSL3HandshakeLock(ss
));
475 PORT_Assert(ss
->opt
.noLocks
|| ssl_HaveXmitBufLock(ss
));
477 msg
= dtls_AllocQueuedMessage(ss
->ssl3
.cwSpec
->epoch
, type
, pIn
, nIn
);
480 PORT_SetError(SEC_ERROR_NO_MEMORY
);
483 PR_APPEND_LINK(&msg
->link
, &ss
->ssl3
.hs
.lastMessageFlight
);
489 /* Add DTLS handshake message to the pending queue
490 * Empty the sendBuf buffer.
491 * This function returns SECSuccess or SECFailure, never SECWouldBlock.
492 * Always set sendBuf.len to 0, even when returning SECFailure.
495 * ssl3_AppendHandshakeHeader()
496 * dtls_FlushHandshake()
499 dtls_StageHandshakeMessage(sslSocket
*ss
)
501 SECStatus rv
= SECSuccess
;
503 PORT_Assert(ss
->opt
.noLocks
|| ssl_HaveSSL3HandshakeLock(ss
));
504 PORT_Assert(ss
->opt
.noLocks
|| ssl_HaveXmitBufLock(ss
));
506 /* This function is sometimes called when no data is actually to
507 * be staged, so just return SECSuccess. */
508 if (!ss
->sec
.ci
.sendBuf
.buf
|| !ss
->sec
.ci
.sendBuf
.len
)
511 rv
= dtls_QueueMessage(ss
, content_handshake
,
512 ss
->sec
.ci
.sendBuf
.buf
, ss
->sec
.ci
.sendBuf
.len
);
514 /* Whether we succeeded or failed, toss the old handshake data. */
515 ss
->sec
.ci
.sendBuf
.len
= 0;
519 /* Enqueue the handshake message in sendBuf (if any) and then
520 * transmit the resulting flight of handshake messages.
523 * ssl3_FlushHandshake()
526 dtls_FlushHandshakeMessages(sslSocket
*ss
, PRInt32 flags
)
528 SECStatus rv
= SECSuccess
;
530 PORT_Assert(ss
->opt
.noLocks
|| ssl_HaveSSL3HandshakeLock(ss
));
531 PORT_Assert(ss
->opt
.noLocks
|| ssl_HaveXmitBufLock(ss
));
533 rv
= dtls_StageHandshakeMessage(ss
);
534 if (rv
!= SECSuccess
)
537 if (!(flags
& ssl_SEND_FLAG_FORCE_INTO_BUFFER
)) {
538 rv
= dtls_TransmitMessageFlight(ss
);
539 if (rv
!= SECSuccess
)
542 if (!(flags
& ssl_SEND_FLAG_NO_RETRANSMIT
)) {
543 ss
->ssl3
.hs
.rtRetries
= 0;
544 rv
= dtls_StartTimer(ss
, dtls_RetransmitTimerExpiredCb
);
551 /* The callback for when the retransmit timer expires
555 * dtls_HandleHandshake()
558 dtls_RetransmitTimerExpiredCb(sslSocket
*ss
)
560 SECStatus rv
= SECFailure
;
562 ss
->ssl3
.hs
.rtRetries
++;
564 if (!(ss
->ssl3
.hs
.rtRetries
% 3)) {
565 /* If one of the messages was potentially greater than > MTU,
566 * then downgrade. Do this every time we have retransmitted a
567 * message twice, per RFC 6347 Sec. 4.1.1 */
568 dtls_SetMTU(ss
, ss
->ssl3
.hs
.maxMessageSent
- 1);
571 rv
= dtls_TransmitMessageFlight(ss
);
572 if (rv
== SECSuccess
) {
574 /* Re-arm the timer */
575 rv
= dtls_RestartTimer(ss
, PR_TRUE
, dtls_RetransmitTimerExpiredCb
);
578 if (rv
== SECFailure
) {
579 /* XXX OK for now. In future maybe signal the stack that we couldn't
580 * transmit. For now, let the read handle any real network errors */
584 /* Transmit a flight of handshake messages, stuffing them
585 * into as few records as seems reasonable
588 * dtls_FlushHandshake()
589 * dtls_RetransmitTimerExpiredCb()
592 dtls_TransmitMessageFlight(sslSocket
*ss
)
594 SECStatus rv
= SECSuccess
;
596 PRUint16 room_left
= ss
->ssl3
.mtu
;
599 ssl_GetXmitBufLock(ss
);
600 ssl_GetSpecReadLock(ss
);
602 /* DTLS does not buffer its handshake messages in
603 * ss->pendingBuf, but rather in the lastMessageFlight
604 * structure. This is just a sanity check that
605 * some programming error hasn't inadvertantly
606 * stuffed something in ss->pendingBuf
608 PORT_Assert(!ss
->pendingBuf
.len
);
609 for (msg_p
= PR_LIST_HEAD(&ss
->ssl3
.hs
.lastMessageFlight
);
610 msg_p
!= &ss
->ssl3
.hs
.lastMessageFlight
;
611 msg_p
= PR_NEXT_LINK(msg_p
)) {
612 DTLSQueuedMessage
*msg
= (DTLSQueuedMessage
*)msg_p
;
614 /* The logic here is:
616 * 1. If this is a message that will not fit into the remaining
618 * 2. If the message will now fit into the remaining space,
619 * encrypt, buffer, and loop.
620 * 3. If the message will not fit, then fragment.
622 * At the end of the function, flush.
624 if ((msg
->len
+ SSL3_BUFFER_FUDGE
) > room_left
) {
625 /* The message will not fit into the remaining space, so flush */
626 rv
= dtls_SendSavedWriteData(ss
);
627 if (rv
!= SECSuccess
)
630 room_left
= ss
->ssl3
.mtu
;
633 if ((msg
->len
+ SSL3_BUFFER_FUDGE
) <= room_left
) {
634 /* The message will fit, so encrypt and then continue with the
636 sent
= ssl3_SendRecord(ss
, msg
->epoch
, msg
->type
,
638 ssl_SEND_FLAG_FORCE_INTO_BUFFER
|
639 ssl_SEND_FLAG_USE_EPOCH
);
640 if (sent
!= msg
->len
) {
643 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE
);
648 room_left
= ss
->ssl3
.mtu
- ss
->pendingBuf
.len
;
650 /* The message will not fit, so fragment.
652 * XXX OK for now. Arrange to coalesce the last fragment
653 * of this message with the next message if possible.
654 * That would be more efficient.
656 PRUint32 fragment_offset
= 0;
657 unsigned char fragment
[DTLS_MAX_MTU
]; /* >= than largest
660 /* Assert that we have already flushed */
661 PORT_Assert(room_left
== ss
->ssl3
.mtu
);
663 /* Case 3: We now need to fragment this message
664 * DTLS only supports fragmenting handshaking messages */
665 PORT_Assert(msg
->type
== content_handshake
);
667 /* The headers consume 12 bytes so the smalles possible
668 * message (i.e., an empty one) is 12 bytes
670 PORT_Assert(msg
->len
>= 12);
672 while ((fragment_offset
+ 12) < msg
->len
) {
673 PRUint32 fragment_len
;
674 const unsigned char *content
= msg
->data
+ 12;
675 PRUint32 content_len
= msg
->len
- 12;
677 /* The reason we use 8 here is that that's the length of
678 * the new DTLS data that we add to the header */
679 fragment_len
= PR_MIN(room_left
- (SSL3_BUFFER_FUDGE
+ 8),
680 content_len
- fragment_offset
);
681 PORT_Assert(fragment_len
< DTLS_MAX_MTU
- 12);
682 /* Make totally sure that we are within the buffer.
683 * Note that the only way that fragment len could get
684 * adjusted here is if
686 * (a) we are in release mode so the PORT_Assert is compiled out
687 * (b) either the MTU table is inconsistent with DTLS_MAX_MTU
688 * or ss->ssl3.mtu has become corrupt.
690 fragment_len
= PR_MIN(fragment_len
, DTLS_MAX_MTU
- 12);
692 /* Construct an appropriate-sized fragment */
693 /* Type, length, sequence */
694 PORT_Memcpy(fragment
, msg
->data
, 6);
697 fragment
[6] = (fragment_offset
>> 16) & 0xff;
698 fragment
[7] = (fragment_offset
>> 8) & 0xff;
699 fragment
[8] = (fragment_offset
) & 0xff;
701 /* Fragment length */
702 fragment
[9] = (fragment_len
>> 16) & 0xff;
703 fragment
[10] = (fragment_len
>> 8) & 0xff;
704 fragment
[11] = (fragment_len
) & 0xff;
706 PORT_Memcpy(fragment
+ 12, content
+ fragment_offset
,
710 * Send the record. We do this in two stages
713 sent
= ssl3_SendRecord(ss
, msg
->epoch
, msg
->type
,
714 fragment
, fragment_len
+ 12,
715 ssl_SEND_FLAG_FORCE_INTO_BUFFER
|
716 ssl_SEND_FLAG_USE_EPOCH
);
717 if (sent
!= (fragment_len
+ 12)) {
720 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE
);
726 rv
= dtls_SendSavedWriteData(ss
);
727 if (rv
!= SECSuccess
)
730 fragment_offset
+= fragment_len
;
735 /* Finally, we need to flush */
736 if (rv
== SECSuccess
)
737 rv
= dtls_SendSavedWriteData(ss
);
739 /* Give up the locks */
740 ssl_ReleaseSpecReadLock(ss
);
741 ssl_ReleaseXmitBufLock(ss
);
746 /* Flush the data in the pendingBuf and update the max message sent
747 * so we can adjust the MTU estimate if we need to.
748 * Wrapper for ssl_SendSavedWriteData.
750 * Called from dtls_TransmitMessageFlight()
753 SECStatus
dtls_SendSavedWriteData(sslSocket
*ss
)
757 sent
= ssl_SendSavedWriteData(ss
);
761 /* We should always have complete writes b/c datagram sockets
762 * don't really block */
763 if (ss
->pendingBuf
.len
> 0) {
764 ssl_MapLowLevelError(SSL_ERROR_SOCKET_WRITE_FAILURE
);
768 /* Update the largest message sent so we can adjust the MTU
769 * estimate if necessary */
770 if (sent
> ss
->ssl3
.hs
.maxMessageSent
)
771 ss
->ssl3
.hs
.maxMessageSent
= sent
;
776 /* Compress, MAC, encrypt a DTLS record. Allows specification of
777 * the epoch using epoch value. If use_epoch is PR_TRUE then
778 * we use the provided epoch. If use_epoch is PR_FALSE then
779 * whatever the current value is in effect is used.
781 * Called from ssl3_SendRecord()
784 dtls_CompressMACEncryptRecord(sslSocket
* ss
,
787 SSL3ContentType type
,
788 const SSL3Opaque
* pIn
,
792 SECStatus rv
= SECFailure
;
793 ssl3CipherSpec
* cwSpec
;
795 ssl_GetSpecReadLock(ss
); /********************************/
797 /* The reason for this switch-hitting code is that we might have
798 * a flight of records spanning an epoch boundary, e.g.,
800 * ClientKeyExchange (epoch = 0)
801 * ChangeCipherSpec (epoch = 0)
802 * Finished (epoch = 1)
804 * Thus, each record needs a different cipher spec. The information
805 * about which epoch to use is carried with the record.
808 if (ss
->ssl3
.cwSpec
->epoch
== epoch
)
809 cwSpec
= ss
->ssl3
.cwSpec
;
810 else if (ss
->ssl3
.pwSpec
->epoch
== epoch
)
811 cwSpec
= ss
->ssl3
.pwSpec
;
815 cwSpec
= ss
->ssl3
.cwSpec
;
819 rv
= ssl3_CompressMACEncryptRecord(cwSpec
, ss
->sec
.isServer
, PR_TRUE
,
820 PR_FALSE
, type
, pIn
, contentLen
,
823 PR_NOT_REACHED("Couldn't find a cipher spec matching epoch");
824 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE
);
826 ssl_ReleaseSpecReadLock(ss
); /************************************/
834 * dtls_HandleHandshake()
835 * dtls_FlushHAndshake()
836 * dtls_RestartTimer()
839 dtls_StartTimer(sslSocket
*ss
, DTLSTimerCb cb
)
841 PORT_Assert(ss
->ssl3
.hs
.rtTimerCb
== NULL
);
843 ss
->ssl3
.hs
.rtTimerStarted
= PR_IntervalNow();
844 ss
->ssl3
.hs
.rtTimerCb
= cb
;
849 /* Restart a timer with optional backoff
851 * Called from dtls_RetransmitTimerExpiredCb()
854 dtls_RestartTimer(sslSocket
*ss
, PRBool backoff
, DTLSTimerCb cb
)
857 ss
->ssl3
.hs
.rtTimeoutMs
*= 2;
858 if (ss
->ssl3
.hs
.rtTimeoutMs
> MAX_DTLS_TIMEOUT_MS
)
859 ss
->ssl3
.hs
.rtTimeoutMs
= MAX_DTLS_TIMEOUT_MS
;
862 return dtls_StartTimer(ss
, cb
);
865 /* Cancel a pending timer
868 * dtls_HandleHandshake()
872 dtls_CancelTimer(sslSocket
*ss
)
874 PORT_Assert(ss
->opt
.noLocks
|| ssl_HaveRecvBufLock(ss
));
876 ss
->ssl3
.hs
.rtTimerCb
= NULL
;
879 /* Check the pending timer and fire the callback if it expired
881 * Called from ssl3_GatherCompleteHandshake()
884 dtls_CheckTimer(sslSocket
*ss
)
886 if (!ss
->ssl3
.hs
.rtTimerCb
)
889 if ((PR_IntervalNow() - ss
->ssl3
.hs
.rtTimerStarted
) >
890 PR_MillisecondsToInterval(ss
->ssl3
.hs
.rtTimeoutMs
)) {
891 /* Timer has expired */
892 DTLSTimerCb cb
= ss
->ssl3
.hs
.rtTimerCb
;
894 /* Cancel the timer so that we can call the CB safely */
895 dtls_CancelTimer(ss
);
897 /* Now call the CB */
902 /* The callback to fire when the holddown timer for the Finished
903 * message expires and we can delete it
905 * Called from dtls_CheckTimer()
908 dtls_FinishedTimerCb(sslSocket
*ss
)
910 ssl3_DestroyCipherSpec(ss
->ssl3
.pwSpec
, PR_FALSE
);
913 /* Cancel the Finished hold-down timer and destroy the
914 * pending cipher spec. Note that this means that
915 * successive rehandshakes will fail if the Finished is
918 * XXX OK for now. Figure out how to handle the combination
919 * of Finished lost and rehandshake
922 dtls_RehandshakeCleanup(sslSocket
*ss
)
924 dtls_CancelTimer(ss
);
925 ssl3_DestroyCipherSpec(ss
->ssl3
.pwSpec
, PR_FALSE
);
926 ss
->ssl3
.hs
.sendMessageSeq
= 0;
927 ss
->ssl3
.hs
.recvMessageSeq
= 0;
930 /* Set the MTU to the next step less than or equal to the
931 * advertised value. Also used to downgrade the MTU by
932 * doing dtls_SetMTU(ss, biggest packet set).
934 * Passing 0 means set this to the largest MTU known
935 * (effectively resetting the PMTU backoff value).
939 * dtls_RetransmitTimerExpiredCb()
942 dtls_SetMTU(sslSocket
*ss
, PRUint16 advertised
)
946 if (advertised
== 0) {
947 ss
->ssl3
.mtu
= COMMON_MTU_VALUES
[0];
948 SSL_TRC(30, ("Resetting MTU to %d", ss
->ssl3
.mtu
));
952 for (i
= 0; i
< PR_ARRAY_SIZE(COMMON_MTU_VALUES
); i
++) {
953 if (COMMON_MTU_VALUES
[i
] <= advertised
) {
954 ss
->ssl3
.mtu
= COMMON_MTU_VALUES
[i
];
955 SSL_TRC(30, ("Resetting MTU to %d", ss
->ssl3
.mtu
));
961 ss
->ssl3
.mtu
= COMMON_MTU_VALUES
[PR_ARRAY_SIZE(COMMON_MTU_VALUES
)-1];
962 SSL_TRC(30, ("Resetting MTU to %d", ss
->ssl3
.mtu
));
965 /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a
966 * DTLS hello_verify_request
967 * Caller must hold Handshake and RecvBuf locks.
970 dtls_HandleHelloVerifyRequest(sslSocket
*ss
, SSL3Opaque
*b
, PRUint32 length
)
972 int errCode
= SSL_ERROR_RX_MALFORMED_HELLO_VERIFY_REQUEST
;
975 SECItem cookie
= {siBuffer
, NULL
, 0};
976 SSL3AlertDescription desc
= illegal_parameter
;
978 SSL_TRC(3, ("%d: SSL3[%d]: handle hello_verify_request handshake",
979 SSL_GETPID(), ss
->fd
));
980 PORT_Assert(ss
->opt
.noLocks
|| ssl_HaveRecvBufLock(ss
));
981 PORT_Assert(ss
->opt
.noLocks
|| ssl_HaveSSL3HandshakeLock(ss
));
983 if (ss
->ssl3
.hs
.ws
!= wait_server_hello
) {
984 errCode
= SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST
;
985 desc
= unexpected_message
;
990 temp
= ssl3_ConsumeHandshakeNumber(ss
, 2, &b
, &length
);
992 goto loser
; /* alert has been sent */
995 if (temp
!= SSL_LIBRARY_VERSION_DTLS_1_0_WIRE
&&
996 temp
!= SSL_LIBRARY_VERSION_DTLS_1_2_WIRE
) {
1001 rv
= ssl3_ConsumeHandshakeVariable(ss
, &cookie
, 1, &b
, &length
);
1002 if (rv
!= SECSuccess
) {
1003 goto loser
; /* alert has been sent */
1005 if (cookie
.len
> DTLS_COOKIE_BYTES
) {
1006 desc
= decode_error
;
1007 goto alert_loser
; /* malformed. */
1010 PORT_Memcpy(ss
->ssl3
.hs
.cookie
, cookie
.data
, cookie
.len
);
1011 ss
->ssl3
.hs
.cookieLen
= cookie
.len
;
1014 ssl_GetXmitBufLock(ss
); /*******************************/
1016 /* Now re-send the client hello */
1017 rv
= ssl3_SendClientHello(ss
, PR_TRUE
);
1019 ssl_ReleaseXmitBufLock(ss
); /*******************************/
1021 if (rv
== SECSuccess
)
1025 (void)SSL3_SendAlert(ss
, alert_fatal
, desc
);
1028 errCode
= ssl_MapLowLevelError(errCode
);
1032 /* Initialize the DTLS anti-replay window
1035 * ssl3_SetupPendingCipherSpec()
1036 * ssl3_InitCipherSpec()
1039 dtls_InitRecvdRecords(DTLSRecvdRecords
*records
)
1041 PORT_Memset(records
->data
, 0, sizeof(records
->data
));
1043 records
->right
= DTLS_RECVD_RECORDS_WINDOW
- 1;
1047 * Has this DTLS record been received? Return values are:
1048 * -1 -- out of range to the left
1049 * 0 -- not received yet
1052 * Called from: dtls_HandleRecord()
1055 dtls_RecordGetRecvd(DTLSRecvdRecords
*records
, PRUint64 seq
)
1059 /* Out of range to the left */
1060 if (seq
< records
->left
) {
1064 /* Out of range to the right; since we advance the window on
1065 * receipt, that means that this packet has not been received
1067 if (seq
> records
->right
)
1070 offset
= seq
% DTLS_RECVD_RECORDS_WINDOW
;
1072 return !!(records
->data
[offset
/ 8] & (1 << (offset
% 8)));
1075 /* Update the DTLS anti-replay window
1077 * Called from ssl3_HandleRecord()
1080 dtls_RecordSetRecvd(DTLSRecvdRecords
*records
, PRUint64 seq
)
1084 if (seq
< records
->left
)
1087 if (seq
> records
->right
) {
1092 /* Slide to the right; this is the tricky part
1094 * 1. new_top is set to have room for seq, on the
1095 * next byte boundary by setting the right 8
1097 * 2. new_left is set to compensate.
1098 * 3. Zero all bits between top and new_top. Since
1099 * this is a ring, this zeroes everything as-yet
1100 * unseen. Because we always operate on byte
1101 * boundaries, we can zero one byte at a time
1103 new_right
= seq
| 0x07;
1104 new_left
= (new_right
- DTLS_RECVD_RECORDS_WINDOW
) + 1;
1106 for (right
= records
->right
+ 8; right
<= new_right
; right
+= 8) {
1107 offset
= right
% DTLS_RECVD_RECORDS_WINDOW
;
1108 records
->data
[offset
/ 8] = 0;
1111 records
->right
= new_right
;
1112 records
->left
= new_left
;
1115 offset
= seq
% DTLS_RECVD_RECORDS_WINDOW
;
1117 records
->data
[offset
/ 8] |= (1 << (offset
% 8));
1121 DTLS_GetHandshakeTimeout(PRFileDesc
*socket
, PRIntervalTime
*timeout
)
1123 sslSocket
* ss
= NULL
;
1124 PRIntervalTime elapsed
;
1125 PRIntervalTime desired
;
1127 ss
= ssl_FindSocket(socket
);
1135 if (!ss
->ssl3
.hs
.rtTimerCb
)
1138 elapsed
= PR_IntervalNow() - ss
->ssl3
.hs
.rtTimerStarted
;
1139 desired
= PR_MillisecondsToInterval(ss
->ssl3
.hs
.rtTimeoutMs
);
1140 if (elapsed
> desired
) {
1142 *timeout
= PR_INTERVAL_NO_WAIT
;
1144 *timeout
= desired
- elapsed
;