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