/src/mozilla-central/security/nss/lib/ssl/dtls13con.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
3 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
4 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
5 | | |
6 | | /* |
7 | | * DTLS 1.3 Protocol |
8 | | */ |
9 | | |
10 | | #include "ssl.h" |
11 | | #include "sslimpl.h" |
12 | | #include "sslproto.h" |
13 | | |
14 | | SECStatus |
15 | | dtls13_InsertCipherTextHeader(const sslSocket *ss, ssl3CipherSpec *cwSpec, |
16 | | sslBuffer *wrBuf, PRBool *needsLength) |
17 | 0 | { |
18 | 0 | PRUint32 seq; |
19 | 0 | SECStatus rv; |
20 | 0 |
|
21 | 0 | /* Avoid using short records for the handshake. We pack multiple records |
22 | 0 | * into the one datagram for the handshake. */ |
23 | 0 | if (ss->opt.enableDtlsShortHeader && |
24 | 0 | cwSpec->epoch != TrafficKeyHandshake) { |
25 | 0 | *needsLength = PR_FALSE; |
26 | 0 | /* The short header is comprised of two octets in the form |
27 | 0 | * 0b001essssssssssss where 'e' is the low bit of the epoch and 's' is |
28 | 0 | * the low 12 bits of the sequence number. */ |
29 | 0 | seq = 0x2000 | |
30 | 0 | (((uint64_t)cwSpec->epoch & 1) << 12) | |
31 | 0 | (cwSpec->nextSeqNum & 0xfff); |
32 | 0 | return sslBuffer_AppendNumber(wrBuf, seq, 2); |
33 | 0 | } |
34 | 0 |
|
35 | 0 | rv = sslBuffer_AppendNumber(wrBuf, ssl_ct_application_data, 1); |
36 | 0 | if (rv != SECSuccess) { |
37 | 0 | return SECFailure; |
38 | 0 | } |
39 | 0 | |
40 | 0 | /* The epoch and sequence number are encoded on 4 octets, with the epoch |
41 | 0 | * consuming the first two bits. */ |
42 | 0 | seq = (((uint64_t)cwSpec->epoch & 3) << 30) | (cwSpec->nextSeqNum & 0x3fffffff); |
43 | 0 | rv = sslBuffer_AppendNumber(wrBuf, seq, 4); |
44 | 0 | if (rv != SECSuccess) { |
45 | 0 | return SECFailure; |
46 | 0 | } |
47 | 0 | *needsLength = PR_TRUE; |
48 | 0 | return SECSuccess; |
49 | 0 | } |
50 | | |
51 | | /* DTLS 1.3 Record map for ACK processing. |
52 | | * This represents a single fragment, so a record which includes |
53 | | * multiple fragments will have one entry for each fragment on the |
54 | | * sender. We use the same structure on the receiver for convenience |
55 | | * but the only value we actually use is |record|. |
56 | | */ |
57 | | typedef struct DTLSHandshakeRecordEntryStr { |
58 | | PRCList link; |
59 | | PRUint16 messageSeq; /* The handshake message sequence number. */ |
60 | | PRUint32 offset; /* The offset into the handshake message. */ |
61 | | PRUint32 length; /* The length of the fragment. */ |
62 | | sslSequenceNumber record; /* The record (includes epoch). */ |
63 | | PRBool acked; /* Has this packet been acked. */ |
64 | | } DTLSHandshakeRecordEntry; |
65 | | |
66 | | /* Combine the epoch and sequence number into a single value. */ |
67 | | static inline sslSequenceNumber |
68 | | dtls_CombineSequenceNumber(DTLSEpoch epoch, sslSequenceNumber seqNum) |
69 | 0 | { |
70 | 0 | PORT_Assert(seqNum <= RECORD_SEQ_MAX); |
71 | 0 | return ((sslSequenceNumber)epoch << 48) | seqNum; |
72 | 0 | } |
73 | | |
74 | | SECStatus |
75 | | dtls13_RememberFragment(sslSocket *ss, |
76 | | PRCList *list, |
77 | | PRUint32 sequence, |
78 | | PRUint32 offset, |
79 | | PRUint32 length, |
80 | | DTLSEpoch epoch, |
81 | | sslSequenceNumber record) |
82 | 0 | { |
83 | 0 | DTLSHandshakeRecordEntry *entry; |
84 | 0 |
|
85 | 0 | PORT_Assert(IS_DTLS(ss)); |
86 | 0 | /* We should never send an empty fragment with offset > 0. */ |
87 | 0 | PORT_Assert(length || !offset); |
88 | 0 |
|
89 | 0 | if (!tls13_MaybeTls13(ss)) { |
90 | 0 | return SECSuccess; |
91 | 0 | } |
92 | 0 | |
93 | 0 | SSL_TRC(20, ("%d: SSL3[%d]: %s remembering %s record=%llx msg=%d offset=%d", |
94 | 0 | SSL_GETPID(), ss->fd, |
95 | 0 | SSL_ROLE(ss), |
96 | 0 | list == &ss->ssl3.hs.dtlsSentHandshake ? "sent" : "received", |
97 | 0 | dtls_CombineSequenceNumber(epoch, record), sequence, offset)); |
98 | 0 |
|
99 | 0 | entry = PORT_ZAlloc(sizeof(DTLSHandshakeRecordEntry)); |
100 | 0 | if (!entry) { |
101 | 0 | return SECFailure; |
102 | 0 | } |
103 | 0 | |
104 | 0 | entry->messageSeq = sequence; |
105 | 0 | entry->offset = offset; |
106 | 0 | entry->length = length; |
107 | 0 | entry->record = dtls_CombineSequenceNumber(epoch, record); |
108 | 0 | entry->acked = PR_FALSE; |
109 | 0 |
|
110 | 0 | PR_APPEND_LINK(&entry->link, list); |
111 | 0 |
|
112 | 0 | return SECSuccess; |
113 | 0 | } |
114 | | |
115 | | SECStatus |
116 | | dtls13_SendAck(sslSocket *ss) |
117 | 0 | { |
118 | 0 | sslBuffer buf = SSL_BUFFER_EMPTY; |
119 | 0 | SECStatus rv = SECSuccess; |
120 | 0 | PRCList *cursor; |
121 | 0 | PRInt32 sent; |
122 | 0 | unsigned int offset; |
123 | 0 |
|
124 | 0 | SSL_TRC(10, ("%d: SSL3[%d]: Sending ACK", |
125 | 0 | SSL_GETPID(), ss->fd)); |
126 | 0 |
|
127 | 0 | rv = sslBuffer_Skip(&buf, 2, &offset); |
128 | 0 | if (rv != SECSuccess) { |
129 | 0 | goto loser; |
130 | 0 | } |
131 | 0 | for (cursor = PR_LIST_HEAD(&ss->ssl3.hs.dtlsRcvdHandshake); |
132 | 0 | cursor != &ss->ssl3.hs.dtlsRcvdHandshake; |
133 | 0 | cursor = PR_NEXT_LINK(cursor)) { |
134 | 0 | DTLSHandshakeRecordEntry *entry = (DTLSHandshakeRecordEntry *)cursor; |
135 | 0 |
|
136 | 0 | SSL_TRC(10, ("%d: SSL3[%d]: ACK for record=%llx", |
137 | 0 | SSL_GETPID(), ss->fd, entry->record)); |
138 | 0 | rv = sslBuffer_AppendNumber(&buf, entry->record, 8); |
139 | 0 | if (rv != SECSuccess) { |
140 | 0 | goto loser; |
141 | 0 | } |
142 | 0 | } |
143 | 0 |
|
144 | 0 | rv = sslBuffer_InsertLength(&buf, offset, 2); |
145 | 0 | if (rv != SECSuccess) { |
146 | 0 | goto loser; |
147 | 0 | } |
148 | 0 | |
149 | 0 | ssl_GetXmitBufLock(ss); |
150 | 0 | sent = ssl3_SendRecord(ss, NULL, ssl_ct_ack, |
151 | 0 | buf.buf, buf.len, 0); |
152 | 0 | ssl_ReleaseXmitBufLock(ss); |
153 | 0 | if (sent != buf.len) { |
154 | 0 | rv = SECFailure; |
155 | 0 | if (sent != -1) { |
156 | 0 | PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
157 | 0 | } |
158 | 0 | } |
159 | 0 |
|
160 | 0 | loser: |
161 | 0 | sslBuffer_Clear(&buf); |
162 | 0 | return rv; |
163 | 0 | } |
164 | | |
165 | | void |
166 | | dtls13_SendAckCb(sslSocket *ss) |
167 | 0 | { |
168 | 0 | if (!IS_DTLS(ss)) { |
169 | 0 | return; |
170 | 0 | } |
171 | 0 | (void)dtls13_SendAck(ss); |
172 | 0 | } |
173 | | |
174 | | /* Zero length messages are very simple to check. */ |
175 | | static PRBool |
176 | | dtls_IsEmptyMessageAcknowledged(sslSocket *ss, PRUint16 msgSeq, PRUint32 offset) |
177 | 0 | { |
178 | 0 | PRCList *cursor; |
179 | 0 |
|
180 | 0 | for (cursor = PR_LIST_HEAD(&ss->ssl3.hs.dtlsSentHandshake); |
181 | 0 | cursor != &ss->ssl3.hs.dtlsSentHandshake; |
182 | 0 | cursor = PR_NEXT_LINK(cursor)) { |
183 | 0 | DTLSHandshakeRecordEntry *entry = (DTLSHandshakeRecordEntry *)cursor; |
184 | 0 | if (!entry->acked || msgSeq != entry->messageSeq) { |
185 | 0 | continue; |
186 | 0 | } |
187 | 0 | /* Empty fragments are always offset 0. */ |
188 | 0 | if (entry->length == 0) { |
189 | 0 | PORT_Assert(!entry->offset); |
190 | 0 | return PR_TRUE; |
191 | 0 | } |
192 | 0 | } |
193 | 0 | return PR_FALSE; |
194 | 0 | } |
195 | | |
196 | | /* Take a range starting at |*start| and that start forwards based on the |
197 | | * contents of the acknowedgement in |entry|. Only move if the acknowledged |
198 | | * range overlaps |*start|. Return PR_TRUE if it moves. */ |
199 | | static PRBool |
200 | | dtls_MoveUnackedStartForward(DTLSHandshakeRecordEntry *entry, PRUint32 *start) |
201 | 0 | { |
202 | 0 | /* This entry starts too late. */ |
203 | 0 | if (*start < entry->offset) { |
204 | 0 | return PR_FALSE; |
205 | 0 | } |
206 | 0 | /* This entry ends too early. */ |
207 | 0 | if (*start >= entry->offset + entry->length) { |
208 | 0 | return PR_FALSE; |
209 | 0 | } |
210 | 0 | *start = entry->offset + entry->length; |
211 | 0 | return PR_TRUE; |
212 | 0 | } |
213 | | |
214 | | /* Take a range ending at |*end| and move that end backwards based on the |
215 | | * contents of the acknowedgement in |entry|. Only move if the acknowledged |
216 | | * range overlaps |*end|. Return PR_TRUE if it moves. */ |
217 | | static PRBool |
218 | | dtls_MoveUnackedEndBackward(DTLSHandshakeRecordEntry *entry, PRUint32 *end) |
219 | 0 | { |
220 | 0 | /* This entry ends too early. */ |
221 | 0 | if (*end > entry->offset + entry->length) { |
222 | 0 | return PR_FALSE; |
223 | 0 | } |
224 | 0 | /* This entry starts too late. */ |
225 | 0 | if (*end <= entry->offset) { |
226 | 0 | return PR_FALSE; |
227 | 0 | } |
228 | 0 | *end = entry->offset; |
229 | 0 | return PR_TRUE; |
230 | 0 | } |
231 | | |
232 | | /* Get the next contiguous range of unacknowledged bytes from the handshake |
233 | | * message identified by |msgSeq|. The search starts at the offset in |offset|. |
234 | | * |len| contains the full length of the message. |
235 | | * |
236 | | * Returns PR_TRUE if there is an unacknowledged range. In this case, values at |
237 | | * |start| and |end| are modified to contain the range. |
238 | | * |
239 | | * Returns PR_FALSE if the message is entirely acknowledged from |offset| |
240 | | * onwards. |
241 | | */ |
242 | | PRBool |
243 | | dtls_NextUnackedRange(sslSocket *ss, PRUint16 msgSeq, PRUint32 offset, |
244 | | PRUint32 len, PRUint32 *startOut, PRUint32 *endOut) |
245 | 0 | { |
246 | 0 | PRCList *cur_p; |
247 | 0 | PRBool done = PR_FALSE; |
248 | 0 | DTLSHandshakeRecordEntry *entry; |
249 | 0 | PRUint32 start; |
250 | 0 | PRUint32 end; |
251 | 0 |
|
252 | 0 | PORT_Assert(IS_DTLS(ss)); |
253 | 0 |
|
254 | 0 | *startOut = offset; |
255 | 0 | *endOut = len; |
256 | 0 | if (!tls13_MaybeTls13(ss)) { |
257 | 0 | return PR_TRUE; |
258 | 0 | } |
259 | 0 |
|
260 | 0 | /* The message is empty. Use a simple search. */ |
261 | 0 | if (!len) { |
262 | 0 | PORT_Assert(!offset); |
263 | 0 | return !dtls_IsEmptyMessageAcknowledged(ss, msgSeq, offset); |
264 | 0 | } |
265 | 0 |
|
266 | 0 | /* This iterates multiple times over the acknowledgments and only terminates |
267 | 0 | * when an entire iteration happens without start or end moving. If that |
268 | 0 | * happens without start and end crossing each other, then there is a range |
269 | 0 | * of unacknowledged data. If they meet, then the message is fully |
270 | 0 | * acknowledged. */ |
271 | 0 | start = offset; |
272 | 0 | end = len; |
273 | 0 | while (!done) { |
274 | 0 | done = PR_TRUE; |
275 | 0 | for (cur_p = PR_LIST_HEAD(&ss->ssl3.hs.dtlsSentHandshake); |
276 | 0 | cur_p != &ss->ssl3.hs.dtlsSentHandshake; |
277 | 0 | cur_p = PR_NEXT_LINK(cur_p)) { |
278 | 0 | entry = (DTLSHandshakeRecordEntry *)cur_p; |
279 | 0 | if (!entry->acked || msgSeq != entry->messageSeq) { |
280 | 0 | continue; |
281 | 0 | } |
282 | 0 | |
283 | 0 | if (dtls_MoveUnackedStartForward(entry, &start) || |
284 | 0 | dtls_MoveUnackedEndBackward(entry, &end)) { |
285 | 0 | if (start >= end) { |
286 | 0 | /* The message is all acknowledged. */ |
287 | 0 | return PR_FALSE; |
288 | 0 | } |
289 | 0 | /* Start over again and keep going until we don't move either |
290 | 0 | * start or end. */ |
291 | 0 | done = PR_FALSE; |
292 | 0 | break; |
293 | 0 | } |
294 | 0 | } |
295 | 0 | } |
296 | 0 | PORT_Assert(start < end); |
297 | 0 |
|
298 | 0 | *startOut = start; |
299 | 0 | *endOut = end; |
300 | 0 | return PR_TRUE; |
301 | 0 | } |
302 | | |
303 | | SECStatus |
304 | | dtls13_SetupAcks(sslSocket *ss) |
305 | 0 | { |
306 | 0 | if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) { |
307 | 0 | return SECSuccess; |
308 | 0 | } |
309 | 0 | |
310 | 0 | if (ss->ssl3.hs.endOfFlight) { |
311 | 0 | dtls_CancelTimer(ss, ss->ssl3.hs.ackTimer); |
312 | 0 |
|
313 | 0 | if (ss->ssl3.hs.ws == idle_handshake && ss->sec.isServer) { |
314 | 0 | SSL_TRC(10, ("%d: SSL3[%d]: dtls_HandleHandshake, sending ACK", |
315 | 0 | SSL_GETPID(), ss->fd)); |
316 | 0 | return dtls13_SendAck(ss); |
317 | 0 | } |
318 | 0 | return SECSuccess; |
319 | 0 | } |
320 | 0 | |
321 | 0 | /* We need to send an ACK. */ |
322 | 0 | if (!ss->ssl3.hs.ackTimer->cb) { |
323 | 0 | /* We're not armed, so arm. */ |
324 | 0 | SSL_TRC(10, ("%d: SSL3[%d]: dtls_HandleHandshake, arming ack timer", |
325 | 0 | SSL_GETPID(), ss->fd)); |
326 | 0 | return dtls_StartTimer(ss, ss->ssl3.hs.ackTimer, |
327 | 0 | DTLS_RETRANSMIT_INITIAL_MS / 4, |
328 | 0 | dtls13_SendAckCb); |
329 | 0 | } |
330 | 0 | /* The ack timer is already armed, so just return. */ |
331 | 0 | return SECSuccess; |
332 | 0 | } |
333 | | |
334 | | /* |
335 | | * Special case processing for out-of-epoch records. |
336 | | * This can only handle ACKs for now and everything else generates |
337 | | * an error. In future, may also handle KeyUpdate. |
338 | | * |
339 | | * The error checking here is as follows: |
340 | | * |
341 | | * - If it's not encrypted, out of epoch stuff is just discarded. |
342 | | * - If it's encrypted, out of epoch stuff causes an error. |
343 | | */ |
344 | | SECStatus |
345 | | dtls13_HandleOutOfEpochRecord(sslSocket *ss, const ssl3CipherSpec *spec, |
346 | | SSLContentType rType, |
347 | | sslBuffer *databuf) |
348 | 0 | { |
349 | 0 | SECStatus rv; |
350 | 0 | sslBuffer buf = *databuf; |
351 | 0 |
|
352 | 0 | databuf->len = 0; /* Discard data whatever happens. */ |
353 | 0 | PORT_Assert(IS_DTLS(ss)); |
354 | 0 | PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3); |
355 | 0 | /* Can't happen, but double check. */ |
356 | 0 | if (!IS_DTLS(ss) || (ss->version < SSL_LIBRARY_VERSION_TLS_1_3)) { |
357 | 0 | tls13_FatalError(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); |
358 | 0 | return SECFailure; |
359 | 0 | } |
360 | 0 | SSL_TRC(10, ("%d: DTLS13[%d]: handle out of epoch record: type=%d", SSL_GETPID(), |
361 | 0 | ss->fd, rType)); |
362 | 0 |
|
363 | 0 | if (rType == ssl_ct_ack) { |
364 | 0 | ssl_GetSSL3HandshakeLock(ss); |
365 | 0 | rv = dtls13_HandleAck(ss, &buf); |
366 | 0 | ssl_ReleaseSSL3HandshakeLock(ss); |
367 | 0 | PORT_Assert(databuf->len == 0); |
368 | 0 | return rv; |
369 | 0 | } |
370 | 0 |
|
371 | 0 | switch (spec->epoch) { |
372 | 0 | case TrafficKeyClearText: |
373 | 0 | /* Drop. */ |
374 | 0 | return SECSuccess; |
375 | 0 |
|
376 | 0 | case TrafficKeyHandshake: |
377 | 0 | /* Drop out of order handshake messages, but if we are the |
378 | 0 | * server, we might have processed the client's Finished and |
379 | 0 | * moved on to application data keys, but the client has |
380 | 0 | * retransmitted Finished (e.g., because our ACK got lost.) |
381 | 0 | * We just retransmit the previous Finished to let the client |
382 | 0 | * complete. */ |
383 | 0 | if (rType == ssl_ct_handshake) { |
384 | 0 | if ((ss->sec.isServer) && |
385 | 0 | (ss->ssl3.hs.ws == idle_handshake)) { |
386 | 0 | PORT_Assert(dtls_TimerActive(ss, ss->ssl3.hs.hdTimer)); |
387 | 0 | return dtls13_SendAck(ss); |
388 | 0 | } |
389 | 0 | return SECSuccess; |
390 | 0 | } |
391 | 0 | |
392 | 0 | /* This isn't a handshake record, so shouldn't be encrypted |
393 | 0 | * under the handshake key. */ |
394 | 0 | break; |
395 | 0 |
|
396 | 0 | default: |
397 | 0 | /* Any other epoch is forbidden. */ |
398 | 0 | break; |
399 | 0 | } |
400 | 0 | |
401 | 0 | SSL_TRC(10, ("%d: SSL3[%d]: unexpected out of epoch record type %d", SSL_GETPID(), |
402 | 0 | ss->fd, rType)); |
403 | 0 |
|
404 | 0 | (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter); |
405 | 0 | PORT_SetError(SSL_ERROR_RX_UNKNOWN_RECORD_TYPE); |
406 | 0 | return SECFailure; |
407 | 0 | } |
408 | | |
409 | | SECStatus |
410 | | dtls13_HandleAck(sslSocket *ss, sslBuffer *databuf) |
411 | 0 | { |
412 | 0 | PRUint8 *b = databuf->buf; |
413 | 0 | PRUint32 l = databuf->len; |
414 | 0 | unsigned int length; |
415 | 0 | SECStatus rv; |
416 | 0 |
|
417 | 0 | /* Ensure we don't loop. */ |
418 | 0 | databuf->len = 0; |
419 | 0 |
|
420 | 0 | PORT_Assert(IS_DTLS(ss)); |
421 | 0 | if (!tls13_MaybeTls13(ss)) { |
422 | 0 | tls13_FatalError(ss, SSL_ERROR_RX_UNKNOWN_RECORD_TYPE, illegal_parameter); |
423 | 0 | return SECFailure; |
424 | 0 | } |
425 | 0 | |
426 | 0 | SSL_TRC(10, ("%d: SSL3[%d]: Handling ACK", SSL_GETPID(), ss->fd)); |
427 | 0 | rv = ssl3_ConsumeHandshakeNumber(ss, &length, 2, &b, &l); |
428 | 0 | if (rv != SECSuccess) { |
429 | 0 | return SECFailure; |
430 | 0 | } |
431 | 0 | if (length != l) { |
432 | 0 | tls13_FatalError(ss, SSL_ERROR_RX_MALFORMED_DTLS_ACK, decode_error); |
433 | 0 | return SECFailure; |
434 | 0 | } |
435 | 0 | |
436 | 0 | while (l > 0) { |
437 | 0 | PRUint64 seq; |
438 | 0 | PRCList *cursor; |
439 | 0 |
|
440 | 0 | rv = ssl3_ConsumeHandshakeNumber64(ss, &seq, 8, &b, &l); |
441 | 0 | if (rv != SECSuccess) { |
442 | 0 | return SECFailure; |
443 | 0 | } |
444 | 0 | |
445 | 0 | for (cursor = PR_LIST_HEAD(&ss->ssl3.hs.dtlsSentHandshake); |
446 | 0 | cursor != &ss->ssl3.hs.dtlsSentHandshake; |
447 | 0 | cursor = PR_NEXT_LINK(cursor)) { |
448 | 0 | DTLSHandshakeRecordEntry *entry = (DTLSHandshakeRecordEntry *)cursor; |
449 | 0 |
|
450 | 0 | if (entry->record == seq) { |
451 | 0 | SSL_TRC(10, ( |
452 | 0 | "%d: SSL3[%d]: Marking record=%llx message %d offset %d length=%d as ACKed", |
453 | 0 | SSL_GETPID(), ss->fd, |
454 | 0 | seq, entry->messageSeq, entry->offset, entry->length)); |
455 | 0 | entry->acked = PR_TRUE; |
456 | 0 | } |
457 | 0 | } |
458 | 0 | } |
459 | 0 |
|
460 | 0 | /* Try to flush. */ |
461 | 0 | rv = dtls_TransmitMessageFlight(ss); |
462 | 0 | if (rv != SECSuccess) { |
463 | 0 | return SECFailure; |
464 | 0 | } |
465 | 0 | |
466 | 0 | /* Reset the retransmit timer. */ |
467 | 0 | if (ss->ssl3.hs.rtTimer->cb) { |
468 | 0 | (void)dtls_RestartTimer(ss, ss->ssl3.hs.rtTimer); |
469 | 0 | } |
470 | 0 |
|
471 | 0 | /* If there are no more messages to send, cleanup. */ |
472 | 0 | if (PR_CLIST_IS_EMPTY(&ss->ssl3.hs.lastMessageFlight)) { |
473 | 0 | SSL_TRC(10, ("%d: SSL3[%d]: No more unacked handshake messages", |
474 | 0 | SSL_GETPID(), ss->fd)); |
475 | 0 |
|
476 | 0 | dtls_CancelTimer(ss, ss->ssl3.hs.rtTimer); |
477 | 0 | ssl_ClearPRCList(&ss->ssl3.hs.dtlsSentHandshake, NULL); |
478 | 0 | /* If the handshake is finished, and we're the client then |
479 | 0 | * also clean up the handshake read cipher spec. Any ACKs |
480 | 0 | * we receive will be with the application data cipher spec. |
481 | 0 | * The server needs to keep the handshake cipher spec around |
482 | 0 | * for the holddown period to process retransmitted Finisheds. |
483 | 0 | */ |
484 | 0 | if (!ss->sec.isServer && (ss->ssl3.hs.ws == idle_handshake)) { |
485 | 0 | ssl_CipherSpecReleaseByEpoch(ss, CipherSpecRead, |
486 | 0 | TrafficKeyHandshake); |
487 | 0 | } |
488 | 0 | } |
489 | 0 | return SECSuccess; |
490 | 0 | } |
491 | | |
492 | | /* Clean up the read timer for the handshake cipher suites on the |
493 | | * server. |
494 | | * |
495 | | * In DTLS 1.3, the client speaks last (Finished), and will retransmit |
496 | | * until the server ACKs that message (using application data cipher |
497 | | * suites). I.e., |
498 | | * |
499 | | * - The client uses the retransmit timer and retransmits using the |
500 | | * saved write handshake cipher suite. |
501 | | * - The server keeps the saved read handshake cipher suite around |
502 | | * for the holddown period in case it needs to read the Finished. |
503 | | * |
504 | | * After the holddown period, the server assumes the client is happy |
505 | | * and discards the handshake read cipher suite. |
506 | | */ |
507 | | void |
508 | | dtls13_HolddownTimerCb(sslSocket *ss) |
509 | 0 | { |
510 | 0 | SSL_TRC(10, ("%d: SSL3[%d]: holddown timer fired", |
511 | 0 | SSL_GETPID(), ss->fd)); |
512 | 0 | ssl_CipherSpecReleaseByEpoch(ss, CipherSpecRead, TrafficKeyHandshake); |
513 | 0 | ssl_ClearPRCList(&ss->ssl3.hs.dtlsRcvdHandshake, NULL); |
514 | 0 | } |