Coverage Report

Created: 2018-09-25 14:53

/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
}