security/nss/lib/ssl/dtlscon.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/lib/ssl/dtlscon.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1141 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +/*
     1.9 + * DTLS Protocol
    1.10 + */
    1.11 +
    1.12 +#include "ssl.h"
    1.13 +#include "sslimpl.h"
    1.14 +#include "sslproto.h"
    1.15 +
    1.16 +#ifndef PR_ARRAY_SIZE
    1.17 +#define PR_ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
    1.18 +#endif
    1.19 +
    1.20 +static SECStatus dtls_TransmitMessageFlight(sslSocket *ss);
    1.21 +static void dtls_RetransmitTimerExpiredCb(sslSocket *ss);
    1.22 +static SECStatus dtls_SendSavedWriteData(sslSocket *ss);
    1.23 +
    1.24 +/* -28 adjusts for the IP/UDP header */
    1.25 +static const PRUint16 COMMON_MTU_VALUES[] = {
    1.26 +    1500 - 28,  /* Ethernet MTU */
    1.27 +    1280 - 28,  /* IPv6 minimum MTU */
    1.28 +    576 - 28,   /* Common assumption */
    1.29 +    256 - 28    /* We're in serious trouble now */
    1.30 +};
    1.31 +
    1.32 +#define DTLS_COOKIE_BYTES 32
    1.33 +
    1.34 +/* List copied from ssl3con.c:cipherSuites */
    1.35 +static const ssl3CipherSuite nonDTLSSuites[] = {
    1.36 +#ifndef NSS_DISABLE_ECC
    1.37 +    TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
    1.38 +    TLS_ECDHE_RSA_WITH_RC4_128_SHA,
    1.39 +#endif /* NSS_DISABLE_ECC */
    1.40 +    TLS_DHE_DSS_WITH_RC4_128_SHA,
    1.41 +#ifndef NSS_DISABLE_ECC
    1.42 +    TLS_ECDH_RSA_WITH_RC4_128_SHA,
    1.43 +    TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
    1.44 +#endif /* NSS_DISABLE_ECC */
    1.45 +    TLS_RSA_WITH_RC4_128_MD5,
    1.46 +    TLS_RSA_WITH_RC4_128_SHA,
    1.47 +    TLS_RSA_EXPORT1024_WITH_RC4_56_SHA,
    1.48 +    TLS_RSA_EXPORT_WITH_RC4_40_MD5,
    1.49 +    0 /* End of list marker */
    1.50 +};
    1.51 +
    1.52 +/* Map back and forth between TLS and DTLS versions in wire format.
    1.53 + * Mapping table is:
    1.54 + *
    1.55 + * TLS             DTLS
    1.56 + * 1.1 (0302)      1.0 (feff)
    1.57 + * 1.2 (0303)      1.2 (fefd)
    1.58 + */
    1.59 +SSL3ProtocolVersion
    1.60 +dtls_TLSVersionToDTLSVersion(SSL3ProtocolVersion tlsv)
    1.61 +{
    1.62 +    if (tlsv == SSL_LIBRARY_VERSION_TLS_1_1) {
    1.63 +        return SSL_LIBRARY_VERSION_DTLS_1_0_WIRE;
    1.64 +    }
    1.65 +    if (tlsv == SSL_LIBRARY_VERSION_TLS_1_2) {
    1.66 +        return SSL_LIBRARY_VERSION_DTLS_1_2_WIRE;
    1.67 +    }
    1.68 +
    1.69 +    /* Anything other than TLS 1.1 or 1.2 is an error, so return
    1.70 +     * the invalid version 0xffff. */
    1.71 +    return 0xffff;
    1.72 +}
    1.73 +
    1.74 +/* Map known DTLS versions to known TLS versions.
    1.75 + * - Invalid versions (< 1.0) return a version of 0
    1.76 + * - Versions > known return a version one higher than we know of
    1.77 + * to accomodate a theoretically newer version */
    1.78 +SSL3ProtocolVersion
    1.79 +dtls_DTLSVersionToTLSVersion(SSL3ProtocolVersion dtlsv)
    1.80 +{
    1.81 +    if (MSB(dtlsv) == 0xff) {
    1.82 +        return 0;
    1.83 +    }
    1.84 +
    1.85 +    if (dtlsv == SSL_LIBRARY_VERSION_DTLS_1_0_WIRE) {
    1.86 +        return SSL_LIBRARY_VERSION_TLS_1_1;
    1.87 +    }
    1.88 +    if (dtlsv == SSL_LIBRARY_VERSION_DTLS_1_2_WIRE) {
    1.89 +        return SSL_LIBRARY_VERSION_TLS_1_2;
    1.90 +    }
    1.91 +
    1.92 +    /* Return a fictional higher version than we know of */
    1.93 +    return SSL_LIBRARY_VERSION_TLS_1_2 + 1;
    1.94 +}
    1.95 +
    1.96 +/* On this socket, Disable non-DTLS cipher suites in the argument's list */
    1.97 +SECStatus
    1.98 +ssl3_DisableNonDTLSSuites(sslSocket * ss)
    1.99 +{
   1.100 +    const ssl3CipherSuite * suite;
   1.101 +
   1.102 +    for (suite = nonDTLSSuites; *suite; ++suite) {
   1.103 +        SECStatus rv = ssl3_CipherPrefSet(ss, *suite, PR_FALSE);
   1.104 +
   1.105 +        PORT_Assert(rv == SECSuccess); /* else is coding error */
   1.106 +    }
   1.107 +    return SECSuccess;
   1.108 +}
   1.109 +
   1.110 +/* Allocate a DTLSQueuedMessage.
   1.111 + *
   1.112 + * Called from dtls_QueueMessage()
   1.113 + */
   1.114 +static DTLSQueuedMessage *
   1.115 +dtls_AllocQueuedMessage(PRUint16 epoch, SSL3ContentType type,
   1.116 +                        const unsigned char *data, PRUint32 len)
   1.117 +{
   1.118 +    DTLSQueuedMessage *msg = NULL;
   1.119 +
   1.120 +    msg = PORT_ZAlloc(sizeof(DTLSQueuedMessage));
   1.121 +    if (!msg)
   1.122 +        return NULL;
   1.123 +
   1.124 +    msg->data = PORT_Alloc(len);
   1.125 +    if (!msg->data) {
   1.126 +        PORT_Free(msg);
   1.127 +        return NULL;
   1.128 +    }
   1.129 +    PORT_Memcpy(msg->data, data, len);
   1.130 +
   1.131 +    msg->len = len;
   1.132 +    msg->epoch = epoch;
   1.133 +    msg->type = type;
   1.134 +
   1.135 +    return msg;
   1.136 +}
   1.137 +
   1.138 +/*
   1.139 + * Free a handshake message
   1.140 + *
   1.141 + * Called from dtls_FreeHandshakeMessages()
   1.142 + */
   1.143 +static void
   1.144 +dtls_FreeHandshakeMessage(DTLSQueuedMessage *msg)
   1.145 +{
   1.146 +    if (!msg)
   1.147 +        return;
   1.148 +
   1.149 +    PORT_ZFree(msg->data, msg->len);
   1.150 +    PORT_Free(msg);
   1.151 +}
   1.152 +
   1.153 +/*
   1.154 + * Free a list of handshake messages
   1.155 + *
   1.156 + * Called from:
   1.157 + *              dtls_HandleHandshake()
   1.158 + *              ssl3_DestroySSL3Info()
   1.159 + */
   1.160 +void
   1.161 +dtls_FreeHandshakeMessages(PRCList *list)
   1.162 +{
   1.163 +    PRCList *cur_p;
   1.164 +
   1.165 +    while (!PR_CLIST_IS_EMPTY(list)) {
   1.166 +        cur_p = PR_LIST_TAIL(list);
   1.167 +        PR_REMOVE_LINK(cur_p);
   1.168 +        dtls_FreeHandshakeMessage((DTLSQueuedMessage *)cur_p);
   1.169 +    }
   1.170 +}
   1.171 +
   1.172 +/* Called only from ssl3_HandleRecord, for each (deciphered) DTLS record.
   1.173 + * origBuf is the decrypted ssl record content and is expected to contain
   1.174 + * complete handshake records
   1.175 + * Caller must hold the handshake and RecvBuf locks.
   1.176 + *
   1.177 + * Note that this code uses msg_len for two purposes:
   1.178 + *
   1.179 + * (1) To pass the length to ssl3_HandleHandshakeMessage()
   1.180 + * (2) To carry the length of a message currently being reassembled
   1.181 + *
   1.182 + * However, unlike ssl3_HandleHandshake(), it is not used to carry
   1.183 + * the state of reassembly (i.e., whether one is in progress). That
   1.184 + * is carried in recvdHighWater and recvdFragments.
   1.185 + */
   1.186 +#define OFFSET_BYTE(o) (o/8)
   1.187 +#define OFFSET_MASK(o) (1 << (o%8))
   1.188 +
   1.189 +SECStatus
   1.190 +dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
   1.191 +{
   1.192 +    /* XXX OK for now.
   1.193 +     * This doesn't work properly with asynchronous certificate validation.
   1.194 +     * because that returns a WOULDBLOCK error. The current DTLS
   1.195 +     * applications do not need asynchronous validation, but in the
   1.196 +     * future we will need to add this.
   1.197 +     */
   1.198 +    sslBuffer buf = *origBuf;
   1.199 +    SECStatus rv = SECSuccess;
   1.200 +
   1.201 +    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
   1.202 +    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
   1.203 +
   1.204 +    while (buf.len > 0) {
   1.205 +        PRUint8 type;
   1.206 +        PRUint32 message_length;
   1.207 +        PRUint16 message_seq;
   1.208 +        PRUint32 fragment_offset;
   1.209 +        PRUint32 fragment_length;
   1.210 +        PRUint32 offset;
   1.211 +
   1.212 +        if (buf.len < 12) {
   1.213 +            PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
   1.214 +            rv = SECFailure;
   1.215 +            break;
   1.216 +        }
   1.217 +
   1.218 +        /* Parse the header */
   1.219 +        type = buf.buf[0];
   1.220 +        message_length = (buf.buf[1] << 16) | (buf.buf[2] << 8) | buf.buf[3];
   1.221 +        message_seq = (buf.buf[4] << 8) | buf.buf[5];
   1.222 +        fragment_offset = (buf.buf[6] << 16) | (buf.buf[7] << 8) | buf.buf[8];
   1.223 +        fragment_length = (buf.buf[9] << 16) | (buf.buf[10] << 8) | buf.buf[11];
   1.224 +
   1.225 +#define MAX_HANDSHAKE_MSG_LEN 0x1ffff   /* 128k - 1 */
   1.226 +        if (message_length > MAX_HANDSHAKE_MSG_LEN) {
   1.227 +            (void)ssl3_DecodeError(ss);
   1.228 +            PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
   1.229 +            return SECFailure;
   1.230 +        }
   1.231 +#undef MAX_HANDSHAKE_MSG_LEN
   1.232 +
   1.233 +        buf.buf += 12;
   1.234 +        buf.len -= 12;
   1.235 +
   1.236 +        /* This fragment must be complete */
   1.237 +        if (buf.len < fragment_length) {
   1.238 +            PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
   1.239 +            rv = SECFailure;
   1.240 +            break;
   1.241 +        }
   1.242 +
   1.243 +        /* Sanity check the packet contents */
   1.244 +        if ((fragment_length + fragment_offset) > message_length) {
   1.245 +            PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
   1.246 +            rv = SECFailure;
   1.247 +            break;
   1.248 +        }
   1.249 +
   1.250 +        /* There are three ways we could not be ready for this packet.
   1.251 +         *
   1.252 +         * 1. It's a partial next message.
   1.253 +         * 2. It's a partial or complete message beyond the next
   1.254 +         * 3. It's a message we've already seen
   1.255 +         *
   1.256 +         * If it's the complete next message we accept it right away.
   1.257 +         * This is the common case for short messages
   1.258 +         */
   1.259 +        if ((message_seq == ss->ssl3.hs.recvMessageSeq)
   1.260 +            && (fragment_offset == 0)
   1.261 +            && (fragment_length == message_length)) {
   1.262 +            /* Complete next message. Process immediately */
   1.263 +            ss->ssl3.hs.msg_type = (SSL3HandshakeType)type;
   1.264 +            ss->ssl3.hs.msg_len = message_length;
   1.265 +
   1.266 +            /* At this point we are advancing our state machine, so
   1.267 +             * we can free our last flight of messages */
   1.268 +            dtls_FreeHandshakeMessages(&ss->ssl3.hs.lastMessageFlight);
   1.269 +            ss->ssl3.hs.recvdHighWater = -1;
   1.270 +            dtls_CancelTimer(ss);
   1.271 +
   1.272 +            /* Reset the timer to the initial value if the retry counter
   1.273 +             * is 0, per Sec. 4.2.4.1 */
   1.274 +            if (ss->ssl3.hs.rtRetries == 0) {
   1.275 +                ss->ssl3.hs.rtTimeoutMs = INITIAL_DTLS_TIMEOUT_MS;
   1.276 +            }
   1.277 +
   1.278 +            rv = ssl3_HandleHandshakeMessage(ss, buf.buf, ss->ssl3.hs.msg_len);
   1.279 +            if (rv == SECFailure) {
   1.280 +                /* Do not attempt to process rest of messages in this record */
   1.281 +                break;
   1.282 +            }
   1.283 +        } else {
   1.284 +            if (message_seq < ss->ssl3.hs.recvMessageSeq) {
   1.285 +                /* Case 3: we do an immediate retransmit if we're
   1.286 +                 * in a waiting state*/
   1.287 +                if (ss->ssl3.hs.rtTimerCb == NULL) {
   1.288 +                    /* Ignore */
   1.289 +                } else if (ss->ssl3.hs.rtTimerCb ==
   1.290 +                         dtls_RetransmitTimerExpiredCb) {
   1.291 +                    SSL_TRC(30, ("%d: SSL3[%d]: Retransmit detected",
   1.292 +                                 SSL_GETPID(), ss->fd));
   1.293 +                    /* Check to see if we retransmitted recently. If so,
   1.294 +                     * suppress the triggered retransmit. This avoids
   1.295 +                     * retransmit wars after packet loss.
   1.296 +                     * This is not in RFC 5346 but should be
   1.297 +                     */
   1.298 +                    if ((PR_IntervalNow() - ss->ssl3.hs.rtTimerStarted) >
   1.299 +                        (ss->ssl3.hs.rtTimeoutMs / 4)) {
   1.300 +                            SSL_TRC(30,
   1.301 +                            ("%d: SSL3[%d]: Shortcutting retransmit timer",
   1.302 +                            SSL_GETPID(), ss->fd));
   1.303 +
   1.304 +                            /* Cancel the timer and call the CB,
   1.305 +                             * which re-arms the timer */
   1.306 +                            dtls_CancelTimer(ss);
   1.307 +                            dtls_RetransmitTimerExpiredCb(ss);
   1.308 +                            rv = SECSuccess;
   1.309 +                            break;
   1.310 +                        } else {
   1.311 +                            SSL_TRC(30,
   1.312 +                            ("%d: SSL3[%d]: We just retransmitted. Ignoring.",
   1.313 +                            SSL_GETPID(), ss->fd));
   1.314 +                            rv = SECSuccess;
   1.315 +                            break;
   1.316 +                        }
   1.317 +                } else if (ss->ssl3.hs.rtTimerCb == dtls_FinishedTimerCb) {
   1.318 +                    /* Retransmit the messages and re-arm the timer
   1.319 +                     * Note that we are not backing off the timer here.
   1.320 +                     * The spec isn't clear and my reasoning is that this
   1.321 +                     * may be a re-ordered packet rather than slowness,
   1.322 +                     * so let's be aggressive. */
   1.323 +                    dtls_CancelTimer(ss);
   1.324 +                    rv = dtls_TransmitMessageFlight(ss);
   1.325 +                    if (rv == SECSuccess) {
   1.326 +                        rv = dtls_StartTimer(ss, dtls_FinishedTimerCb);
   1.327 +                    }
   1.328 +                    if (rv != SECSuccess)
   1.329 +                        return rv;
   1.330 +                    break;
   1.331 +                }
   1.332 +            } else if (message_seq > ss->ssl3.hs.recvMessageSeq) {
   1.333 +                /* Case 2
   1.334 +                 *
   1.335 +                 * Ignore this message. This means we don't handle out of
   1.336 +                 * order complete messages that well, but we're still
   1.337 +                 * compliant and this probably does not happen often
   1.338 +                 *
   1.339 +                 * XXX OK for now. Maybe do something smarter at some point?
   1.340 +                 */
   1.341 +            } else {
   1.342 +                /* Case 1
   1.343 +                 *
   1.344 +                 * Buffer the fragment for reassembly
   1.345 +                 */
   1.346 +                /* Make room for the message */
   1.347 +                if (ss->ssl3.hs.recvdHighWater == -1) {
   1.348 +                    PRUint32 map_length = OFFSET_BYTE(message_length) + 1;
   1.349 +
   1.350 +                    rv = sslBuffer_Grow(&ss->ssl3.hs.msg_body, message_length);
   1.351 +                    if (rv != SECSuccess)
   1.352 +                        break;
   1.353 +                    /* Make room for the fragment map */
   1.354 +                    rv = sslBuffer_Grow(&ss->ssl3.hs.recvdFragments,
   1.355 +                                        map_length);
   1.356 +                    if (rv != SECSuccess)
   1.357 +                        break;
   1.358 +
   1.359 +                    /* Reset the reassembly map */
   1.360 +                    ss->ssl3.hs.recvdHighWater = 0;
   1.361 +                    PORT_Memset(ss->ssl3.hs.recvdFragments.buf, 0,
   1.362 +                                ss->ssl3.hs.recvdFragments.space);
   1.363 +                    ss->ssl3.hs.msg_type = (SSL3HandshakeType)type;
   1.364 +                    ss->ssl3.hs.msg_len = message_length;
   1.365 +                }
   1.366 +
   1.367 +                /* If we have a message length mismatch, abandon the reassembly
   1.368 +                 * in progress and hope that the next retransmit will give us
   1.369 +                 * something sane
   1.370 +                 */
   1.371 +                if (message_length != ss->ssl3.hs.msg_len) {
   1.372 +                    ss->ssl3.hs.recvdHighWater = -1;
   1.373 +                    PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
   1.374 +                    rv = SECFailure;
   1.375 +                    break;
   1.376 +                }
   1.377 +
   1.378 +                /* Now copy this fragment into the buffer */
   1.379 +                PORT_Assert((fragment_offset + fragment_length) <=
   1.380 +                            ss->ssl3.hs.msg_body.space);
   1.381 +                PORT_Memcpy(ss->ssl3.hs.msg_body.buf + fragment_offset,
   1.382 +                            buf.buf, fragment_length);
   1.383 +
   1.384 +                /* This logic is a bit tricky. We have two values for
   1.385 +                 * reassembly state:
   1.386 +                 *
   1.387 +                 * - recvdHighWater contains the highest contiguous number of
   1.388 +                 *   bytes received
   1.389 +                 * - recvdFragments contains a bitmask of packets received
   1.390 +                 *   above recvdHighWater
   1.391 +                 *
   1.392 +                 * This avoids having to fill in the bitmask in the common
   1.393 +                 * case of adjacent fragments received in sequence
   1.394 +                 */
   1.395 +                if (fragment_offset <= ss->ssl3.hs.recvdHighWater) {
   1.396 +                    /* Either this is the adjacent fragment or an overlapping
   1.397 +                     * fragment */
   1.398 +                    ss->ssl3.hs.recvdHighWater = fragment_offset +
   1.399 +                                                 fragment_length;
   1.400 +                } else {
   1.401 +                    for (offset = fragment_offset;
   1.402 +                         offset < fragment_offset + fragment_length;
   1.403 +                         offset++) {
   1.404 +                        ss->ssl3.hs.recvdFragments.buf[OFFSET_BYTE(offset)] |=
   1.405 +                            OFFSET_MASK(offset);
   1.406 +                    }
   1.407 +                }
   1.408 +
   1.409 +                /* Now figure out the new high water mark if appropriate */
   1.410 +                for (offset = ss->ssl3.hs.recvdHighWater;
   1.411 +                     offset < ss->ssl3.hs.msg_len; offset++) {
   1.412 +                    /* Note that this loop is not efficient, since it counts
   1.413 +                     * bit by bit. If we have a lot of out-of-order packets,
   1.414 +                     * we should optimize this */
   1.415 +                    if (ss->ssl3.hs.recvdFragments.buf[OFFSET_BYTE(offset)] &
   1.416 +                        OFFSET_MASK(offset)) {
   1.417 +                        ss->ssl3.hs.recvdHighWater++;
   1.418 +                    } else {
   1.419 +                        break;
   1.420 +                    }
   1.421 +                }
   1.422 +
   1.423 +                /* If we have all the bytes, then we are good to go */
   1.424 +                if (ss->ssl3.hs.recvdHighWater == ss->ssl3.hs.msg_len) {
   1.425 +                    ss->ssl3.hs.recvdHighWater = -1;
   1.426 +
   1.427 +                    rv = ssl3_HandleHandshakeMessage(ss,
   1.428 +                                                     ss->ssl3.hs.msg_body.buf,
   1.429 +                                                     ss->ssl3.hs.msg_len);
   1.430 +                    if (rv == SECFailure)
   1.431 +                        break; /* Skip rest of record */
   1.432 +
   1.433 +                    /* At this point we are advancing our state machine, so
   1.434 +                     * we can free our last flight of messages */
   1.435 +                    dtls_FreeHandshakeMessages(&ss->ssl3.hs.lastMessageFlight);
   1.436 +                    dtls_CancelTimer(ss);
   1.437 +
   1.438 +                    /* If there have been no retries this time, reset the
   1.439 +                     * timer value to the default per Section 4.2.4.1 */
   1.440 +                    if (ss->ssl3.hs.rtRetries == 0) {
   1.441 +                        ss->ssl3.hs.rtTimeoutMs = INITIAL_DTLS_TIMEOUT_MS;
   1.442 +                    }
   1.443 +                }
   1.444 +            }
   1.445 +        }
   1.446 +
   1.447 +        buf.buf += fragment_length;
   1.448 +        buf.len -= fragment_length;
   1.449 +    }
   1.450 +
   1.451 +    origBuf->len = 0;   /* So ssl3_GatherAppDataRecord will keep looping. */
   1.452 +
   1.453 +    /* XXX OK for now. In future handle rv == SECWouldBlock safely in order
   1.454 +     * to deal with asynchronous certificate verification */
   1.455 +    return rv;
   1.456 +}
   1.457 +
   1.458 +/* Enqueue a message (either handshake or CCS)
   1.459 + *
   1.460 + * Called from:
   1.461 + *              dtls_StageHandshakeMessage()
   1.462 + *              ssl3_SendChangeCipherSpecs()
   1.463 + */
   1.464 +SECStatus dtls_QueueMessage(sslSocket *ss, SSL3ContentType type,
   1.465 +    const SSL3Opaque *pIn, PRInt32 nIn)
   1.466 +{
   1.467 +    SECStatus rv = SECSuccess;
   1.468 +    DTLSQueuedMessage *msg = NULL;
   1.469 +
   1.470 +    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
   1.471 +    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
   1.472 +
   1.473 +    msg = dtls_AllocQueuedMessage(ss->ssl3.cwSpec->epoch, type, pIn, nIn);
   1.474 +
   1.475 +    if (!msg) {
   1.476 +        PORT_SetError(SEC_ERROR_NO_MEMORY);
   1.477 +        rv = SECFailure;
   1.478 +    } else {
   1.479 +        PR_APPEND_LINK(&msg->link, &ss->ssl3.hs.lastMessageFlight);
   1.480 +    }
   1.481 +
   1.482 +    return rv;
   1.483 +}
   1.484 +
   1.485 +/* Add DTLS handshake message to the pending queue
   1.486 + * Empty the sendBuf buffer.
   1.487 + * This function returns SECSuccess or SECFailure, never SECWouldBlock.
   1.488 + * Always set sendBuf.len to 0, even when returning SECFailure.
   1.489 + *
   1.490 + * Called from:
   1.491 + *              ssl3_AppendHandshakeHeader()
   1.492 + *              dtls_FlushHandshake()
   1.493 + */
   1.494 +SECStatus
   1.495 +dtls_StageHandshakeMessage(sslSocket *ss)
   1.496 +{
   1.497 +    SECStatus rv = SECSuccess;
   1.498 +
   1.499 +    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
   1.500 +    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
   1.501 +
   1.502 +    /* This function is sometimes called when no data is actually to
   1.503 +     * be staged, so just return SECSuccess. */
   1.504 +    if (!ss->sec.ci.sendBuf.buf || !ss->sec.ci.sendBuf.len)
   1.505 +        return rv;
   1.506 +
   1.507 +    rv = dtls_QueueMessage(ss, content_handshake,
   1.508 +                           ss->sec.ci.sendBuf.buf, ss->sec.ci.sendBuf.len);
   1.509 +
   1.510 +    /* Whether we succeeded or failed, toss the old handshake data. */
   1.511 +    ss->sec.ci.sendBuf.len = 0;
   1.512 +    return rv;
   1.513 +}
   1.514 +
   1.515 +/* Enqueue the handshake message in sendBuf (if any) and then
   1.516 + * transmit the resulting flight of handshake messages.
   1.517 + *
   1.518 + * Called from:
   1.519 + *              ssl3_FlushHandshake()
   1.520 + */
   1.521 +SECStatus
   1.522 +dtls_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags)
   1.523 +{
   1.524 +    SECStatus rv = SECSuccess;
   1.525 +
   1.526 +    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
   1.527 +    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
   1.528 +
   1.529 +    rv = dtls_StageHandshakeMessage(ss);
   1.530 +    if (rv != SECSuccess)
   1.531 +        return rv;
   1.532 +
   1.533 +    if (!(flags & ssl_SEND_FLAG_FORCE_INTO_BUFFER)) {
   1.534 +        rv = dtls_TransmitMessageFlight(ss);
   1.535 +        if (rv != SECSuccess)
   1.536 +            return rv;
   1.537 +
   1.538 +        if (!(flags & ssl_SEND_FLAG_NO_RETRANSMIT)) {
   1.539 +            ss->ssl3.hs.rtRetries = 0;
   1.540 +            rv = dtls_StartTimer(ss, dtls_RetransmitTimerExpiredCb);
   1.541 +        }
   1.542 +    }
   1.543 +
   1.544 +    return rv;
   1.545 +}
   1.546 +
   1.547 +/* The callback for when the retransmit timer expires
   1.548 + *
   1.549 + * Called from:
   1.550 + *              dtls_CheckTimer()
   1.551 + *              dtls_HandleHandshake()
   1.552 + */
   1.553 +static void
   1.554 +dtls_RetransmitTimerExpiredCb(sslSocket *ss)
   1.555 +{
   1.556 +    SECStatus rv = SECFailure;
   1.557 +
   1.558 +    ss->ssl3.hs.rtRetries++;
   1.559 +
   1.560 +    if (!(ss->ssl3.hs.rtRetries % 3)) {
   1.561 +        /* If one of the messages was potentially greater than > MTU,
   1.562 +         * then downgrade. Do this every time we have retransmitted a
   1.563 +         * message twice, per RFC 6347 Sec. 4.1.1 */
   1.564 +        dtls_SetMTU(ss, ss->ssl3.hs.maxMessageSent - 1);
   1.565 +    }
   1.566 +
   1.567 +    rv = dtls_TransmitMessageFlight(ss);
   1.568 +    if (rv == SECSuccess) {
   1.569 +
   1.570 +        /* Re-arm the timer */
   1.571 +        rv = dtls_RestartTimer(ss, PR_TRUE, dtls_RetransmitTimerExpiredCb);
   1.572 +    }
   1.573 +
   1.574 +    if (rv == SECFailure) {
   1.575 +        /* XXX OK for now. In future maybe signal the stack that we couldn't
   1.576 +         * transmit. For now, let the read handle any real network errors */
   1.577 +    }
   1.578 +}
   1.579 +
   1.580 +/* Transmit a flight of handshake messages, stuffing them
   1.581 + * into as few records as seems reasonable
   1.582 + *
   1.583 + * Called from:
   1.584 + *             dtls_FlushHandshake()
   1.585 + *             dtls_RetransmitTimerExpiredCb()
   1.586 + */
   1.587 +static SECStatus
   1.588 +dtls_TransmitMessageFlight(sslSocket *ss)
   1.589 +{
   1.590 +    SECStatus rv = SECSuccess;
   1.591 +    PRCList *msg_p;
   1.592 +    PRUint16 room_left = ss->ssl3.mtu;
   1.593 +    PRInt32 sent;
   1.594 +
   1.595 +    ssl_GetXmitBufLock(ss);
   1.596 +    ssl_GetSpecReadLock(ss);
   1.597 +
   1.598 +    /* DTLS does not buffer its handshake messages in
   1.599 +     * ss->pendingBuf, but rather in the lastMessageFlight
   1.600 +     * structure. This is just a sanity check that
   1.601 +     * some programming error hasn't inadvertantly
   1.602 +     * stuffed something in ss->pendingBuf
   1.603 +     */
   1.604 +    PORT_Assert(!ss->pendingBuf.len);
   1.605 +    for (msg_p = PR_LIST_HEAD(&ss->ssl3.hs.lastMessageFlight);
   1.606 +         msg_p != &ss->ssl3.hs.lastMessageFlight;
   1.607 +         msg_p = PR_NEXT_LINK(msg_p)) {
   1.608 +        DTLSQueuedMessage *msg = (DTLSQueuedMessage *)msg_p;
   1.609 +
   1.610 +        /* The logic here is:
   1.611 +         *
   1.612 +         * 1. If this is a message that will not fit into the remaining
   1.613 +         *    space, then flush.
   1.614 +         * 2. If the message will now fit into the remaining space,
   1.615 +         *    encrypt, buffer, and loop.
   1.616 +         * 3. If the message will not fit, then fragment.
   1.617 +         *
   1.618 +         * At the end of the function, flush.
   1.619 +         */
   1.620 +        if ((msg->len + SSL3_BUFFER_FUDGE) > room_left) {
   1.621 +            /* The message will not fit into the remaining space, so flush */
   1.622 +            rv = dtls_SendSavedWriteData(ss);
   1.623 +            if (rv != SECSuccess)
   1.624 +                break;
   1.625 +
   1.626 +            room_left = ss->ssl3.mtu;
   1.627 +        }
   1.628 +
   1.629 +        if ((msg->len + SSL3_BUFFER_FUDGE) <= room_left) {
   1.630 +            /* The message will fit, so encrypt and then continue with the
   1.631 +             * next packet */
   1.632 +            sent = ssl3_SendRecord(ss, msg->epoch, msg->type,
   1.633 +                                   msg->data, msg->len,
   1.634 +                                   ssl_SEND_FLAG_FORCE_INTO_BUFFER |
   1.635 +                                   ssl_SEND_FLAG_USE_EPOCH);
   1.636 +            if (sent != msg->len) {
   1.637 +                rv = SECFailure;
   1.638 +                if (sent != -1) {
   1.639 +                    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   1.640 +                }
   1.641 +                break;
   1.642 +            }
   1.643 +
   1.644 +            room_left = ss->ssl3.mtu - ss->pendingBuf.len;
   1.645 +        } else {
   1.646 +            /* The message will not fit, so fragment.
   1.647 +             *
   1.648 +             * XXX OK for now. Arrange to coalesce the last fragment
   1.649 +             * of this message with the next message if possible.
   1.650 +             * That would be more efficient.
   1.651 +             */
   1.652 +            PRUint32 fragment_offset = 0;
   1.653 +            unsigned char fragment[DTLS_MAX_MTU]; /* >= than largest
   1.654 +                                                   * plausible MTU */
   1.655 +
   1.656 +            /* Assert that we have already flushed */
   1.657 +            PORT_Assert(room_left == ss->ssl3.mtu);
   1.658 +
   1.659 +            /* Case 3: We now need to fragment this message
   1.660 +             * DTLS only supports fragmenting handshaking messages */
   1.661 +            PORT_Assert(msg->type == content_handshake);
   1.662 +
   1.663 +            /* The headers consume 12 bytes so the smalles possible
   1.664 +             *  message (i.e., an empty one) is 12 bytes
   1.665 +             */
   1.666 +            PORT_Assert(msg->len >= 12);
   1.667 +
   1.668 +            while ((fragment_offset + 12) < msg->len) {
   1.669 +                PRUint32 fragment_len;
   1.670 +                const unsigned char *content = msg->data + 12;
   1.671 +                PRUint32 content_len = msg->len - 12;
   1.672 +
   1.673 +                /* The reason we use 8 here is that that's the length of
   1.674 +                 * the new DTLS data that we add to the header */
   1.675 +                fragment_len = PR_MIN(room_left - (SSL3_BUFFER_FUDGE + 8),
   1.676 +                                      content_len - fragment_offset);
   1.677 +                PORT_Assert(fragment_len < DTLS_MAX_MTU - 12);
   1.678 +                /* Make totally sure that we are within the buffer.
   1.679 +                 * Note that the only way that fragment len could get
   1.680 +                 * adjusted here is if
   1.681 +                 *
   1.682 +                 * (a) we are in release mode so the PORT_Assert is compiled out
   1.683 +                 * (b) either the MTU table is inconsistent with DTLS_MAX_MTU
   1.684 +                 * or ss->ssl3.mtu has become corrupt.
   1.685 +                 */
   1.686 +                fragment_len = PR_MIN(fragment_len, DTLS_MAX_MTU - 12);
   1.687 +
   1.688 +                /* Construct an appropriate-sized fragment */
   1.689 +                /* Type, length, sequence */
   1.690 +                PORT_Memcpy(fragment, msg->data, 6);
   1.691 +
   1.692 +                /* Offset */
   1.693 +                fragment[6] = (fragment_offset >> 16) & 0xff;
   1.694 +                fragment[7] = (fragment_offset >> 8) & 0xff;
   1.695 +                fragment[8] = (fragment_offset) & 0xff;
   1.696 +
   1.697 +                /* Fragment length */
   1.698 +                fragment[9] = (fragment_len >> 16) & 0xff;
   1.699 +                fragment[10] = (fragment_len >> 8) & 0xff;
   1.700 +                fragment[11] = (fragment_len) & 0xff;
   1.701 +
   1.702 +                PORT_Memcpy(fragment + 12, content + fragment_offset,
   1.703 +                            fragment_len);
   1.704 +
   1.705 +                /*
   1.706 +                 *  Send the record. We do this in two stages
   1.707 +                 * 1. Encrypt
   1.708 +                 */
   1.709 +                sent = ssl3_SendRecord(ss, msg->epoch, msg->type,
   1.710 +                                       fragment, fragment_len + 12,
   1.711 +                                       ssl_SEND_FLAG_FORCE_INTO_BUFFER |
   1.712 +                                       ssl_SEND_FLAG_USE_EPOCH);
   1.713 +                if (sent != (fragment_len + 12)) {
   1.714 +                    rv = SECFailure;
   1.715 +                    if (sent != -1) {
   1.716 +                        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   1.717 +                    }
   1.718 +                    break;
   1.719 +                }
   1.720 +
   1.721 +                /* 2. Flush */
   1.722 +                rv = dtls_SendSavedWriteData(ss);
   1.723 +                if (rv != SECSuccess)
   1.724 +                    break;
   1.725 +
   1.726 +                fragment_offset += fragment_len;
   1.727 +            }
   1.728 +        }
   1.729 +    }
   1.730 +
   1.731 +    /* Finally, we need to flush */
   1.732 +    if (rv == SECSuccess)
   1.733 +        rv = dtls_SendSavedWriteData(ss);
   1.734 +
   1.735 +    /* Give up the locks */
   1.736 +    ssl_ReleaseSpecReadLock(ss);
   1.737 +    ssl_ReleaseXmitBufLock(ss);
   1.738 +
   1.739 +    return rv;
   1.740 +}
   1.741 +
   1.742 +/* Flush the data in the pendingBuf and update the max message sent
   1.743 + * so we can adjust the MTU estimate if we need to.
   1.744 + * Wrapper for ssl_SendSavedWriteData.
   1.745 + *
   1.746 + * Called from dtls_TransmitMessageFlight()
   1.747 + */
   1.748 +static
   1.749 +SECStatus dtls_SendSavedWriteData(sslSocket *ss)
   1.750 +{
   1.751 +    PRInt32 sent;
   1.752 +
   1.753 +    sent = ssl_SendSavedWriteData(ss);
   1.754 +    if (sent < 0)
   1.755 +        return SECFailure;
   1.756 +
   1.757 +    /* We should always have complete writes b/c datagram sockets
   1.758 +     * don't really block */
   1.759 +    if (ss->pendingBuf.len > 0) {
   1.760 +        ssl_MapLowLevelError(SSL_ERROR_SOCKET_WRITE_FAILURE);
   1.761 +        return SECFailure;
   1.762 +    }
   1.763 +
   1.764 +    /* Update the largest message sent so we can adjust the MTU
   1.765 +     * estimate if necessary */
   1.766 +    if (sent > ss->ssl3.hs.maxMessageSent)
   1.767 +        ss->ssl3.hs.maxMessageSent = sent;
   1.768 +
   1.769 +    return SECSuccess;
   1.770 +}
   1.771 +
   1.772 +/* Compress, MAC, encrypt a DTLS record. Allows specification of
   1.773 + * the epoch using epoch value. If use_epoch is PR_TRUE then
   1.774 + * we use the provided epoch. If use_epoch is PR_FALSE then
   1.775 + * whatever the current value is in effect is used.
   1.776 + *
   1.777 + * Called from ssl3_SendRecord()
   1.778 + */
   1.779 +SECStatus
   1.780 +dtls_CompressMACEncryptRecord(sslSocket *        ss,
   1.781 +                              DTLSEpoch          epoch,
   1.782 +                              PRBool             use_epoch,
   1.783 +                              SSL3ContentType    type,
   1.784 +                              const SSL3Opaque * pIn,
   1.785 +                              PRUint32           contentLen,
   1.786 +                              sslBuffer        * wrBuf)
   1.787 +{
   1.788 +    SECStatus rv = SECFailure;
   1.789 +    ssl3CipherSpec *          cwSpec;
   1.790 +
   1.791 +    ssl_GetSpecReadLock(ss);    /********************************/
   1.792 +
   1.793 +    /* The reason for this switch-hitting code is that we might have
   1.794 +     * a flight of records spanning an epoch boundary, e.g.,
   1.795 +     *
   1.796 +     * ClientKeyExchange (epoch = 0)
   1.797 +     * ChangeCipherSpec (epoch = 0)
   1.798 +     * Finished (epoch = 1)
   1.799 +     *
   1.800 +     * Thus, each record needs a different cipher spec. The information
   1.801 +     * about which epoch to use is carried with the record.
   1.802 +     */
   1.803 +    if (use_epoch) {
   1.804 +        if (ss->ssl3.cwSpec->epoch == epoch)
   1.805 +            cwSpec = ss->ssl3.cwSpec;
   1.806 +        else if (ss->ssl3.pwSpec->epoch == epoch)
   1.807 +            cwSpec = ss->ssl3.pwSpec;
   1.808 +        else
   1.809 +            cwSpec = NULL;
   1.810 +    } else {
   1.811 +        cwSpec = ss->ssl3.cwSpec;
   1.812 +    }
   1.813 +
   1.814 +    if (cwSpec) {
   1.815 +        rv = ssl3_CompressMACEncryptRecord(cwSpec, ss->sec.isServer, PR_TRUE,
   1.816 +                                           PR_FALSE, type, pIn, contentLen,
   1.817 +                                           wrBuf);
   1.818 +    } else {
   1.819 +        PR_NOT_REACHED("Couldn't find a cipher spec matching epoch");
   1.820 +        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
   1.821 +    }
   1.822 +    ssl_ReleaseSpecReadLock(ss); /************************************/
   1.823 +
   1.824 +    return rv;
   1.825 +}
   1.826 +
   1.827 +/* Start a timer
   1.828 + *
   1.829 + * Called from:
   1.830 + *             dtls_HandleHandshake()
   1.831 + *             dtls_FlushHAndshake()
   1.832 + *             dtls_RestartTimer()
   1.833 + */
   1.834 +SECStatus
   1.835 +dtls_StartTimer(sslSocket *ss, DTLSTimerCb cb)
   1.836 +{
   1.837 +    PORT_Assert(ss->ssl3.hs.rtTimerCb == NULL);
   1.838 +
   1.839 +    ss->ssl3.hs.rtTimerStarted = PR_IntervalNow();
   1.840 +    ss->ssl3.hs.rtTimerCb = cb;
   1.841 +
   1.842 +    return SECSuccess;
   1.843 +}
   1.844 +
   1.845 +/* Restart a timer with optional backoff
   1.846 + *
   1.847 + * Called from dtls_RetransmitTimerExpiredCb()
   1.848 + */
   1.849 +SECStatus
   1.850 +dtls_RestartTimer(sslSocket *ss, PRBool backoff, DTLSTimerCb cb)
   1.851 +{
   1.852 +    if (backoff) {
   1.853 +        ss->ssl3.hs.rtTimeoutMs *= 2;
   1.854 +        if (ss->ssl3.hs.rtTimeoutMs > MAX_DTLS_TIMEOUT_MS)
   1.855 +            ss->ssl3.hs.rtTimeoutMs = MAX_DTLS_TIMEOUT_MS;
   1.856 +    }
   1.857 +
   1.858 +    return dtls_StartTimer(ss, cb);
   1.859 +}
   1.860 +
   1.861 +/* Cancel a pending timer
   1.862 + *
   1.863 + * Called from:
   1.864 + *              dtls_HandleHandshake()
   1.865 + *              dtls_CheckTimer()
   1.866 + */
   1.867 +void
   1.868 +dtls_CancelTimer(sslSocket *ss)
   1.869 +{
   1.870 +    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
   1.871 +
   1.872 +    ss->ssl3.hs.rtTimerCb = NULL;
   1.873 +}
   1.874 +
   1.875 +/* Check the pending timer and fire the callback if it expired
   1.876 + *
   1.877 + * Called from ssl3_GatherCompleteHandshake()
   1.878 + */
   1.879 +void
   1.880 +dtls_CheckTimer(sslSocket *ss)
   1.881 +{
   1.882 +    if (!ss->ssl3.hs.rtTimerCb)
   1.883 +        return;
   1.884 +
   1.885 +    if ((PR_IntervalNow() - ss->ssl3.hs.rtTimerStarted) >
   1.886 +        PR_MillisecondsToInterval(ss->ssl3.hs.rtTimeoutMs)) {
   1.887 +        /* Timer has expired */
   1.888 +        DTLSTimerCb cb = ss->ssl3.hs.rtTimerCb;
   1.889 +
   1.890 +        /* Cancel the timer so that we can call the CB safely */
   1.891 +        dtls_CancelTimer(ss);
   1.892 +
   1.893 +        /* Now call the CB */
   1.894 +        cb(ss);
   1.895 +    }
   1.896 +}
   1.897 +
   1.898 +/* The callback to fire when the holddown timer for the Finished
   1.899 + * message expires and we can delete it
   1.900 + *
   1.901 + * Called from dtls_CheckTimer()
   1.902 + */
   1.903 +void
   1.904 +dtls_FinishedTimerCb(sslSocket *ss)
   1.905 +{
   1.906 +    ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_FALSE);
   1.907 +}
   1.908 +
   1.909 +/* Cancel the Finished hold-down timer and destroy the
   1.910 + * pending cipher spec. Note that this means that
   1.911 + * successive rehandshakes will fail if the Finished is
   1.912 + * lost.
   1.913 + *
   1.914 + * XXX OK for now. Figure out how to handle the combination
   1.915 + * of Finished lost and rehandshake
   1.916 + */
   1.917 +void
   1.918 +dtls_RehandshakeCleanup(sslSocket *ss)
   1.919 +{
   1.920 +    dtls_CancelTimer(ss);
   1.921 +    ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_FALSE);
   1.922 +    ss->ssl3.hs.sendMessageSeq = 0;
   1.923 +    ss->ssl3.hs.recvMessageSeq = 0;
   1.924 +}
   1.925 +
   1.926 +/* Set the MTU to the next step less than or equal to the
   1.927 + * advertised value. Also used to downgrade the MTU by
   1.928 + * doing dtls_SetMTU(ss, biggest packet set).
   1.929 + *
   1.930 + * Passing 0 means set this to the largest MTU known
   1.931 + * (effectively resetting the PMTU backoff value).
   1.932 + *
   1.933 + * Called by:
   1.934 + *            ssl3_InitState()
   1.935 + *            dtls_RetransmitTimerExpiredCb()
   1.936 + */
   1.937 +void
   1.938 +dtls_SetMTU(sslSocket *ss, PRUint16 advertised)
   1.939 +{
   1.940 +    int i;
   1.941 +
   1.942 +    if (advertised == 0) {
   1.943 +        ss->ssl3.mtu = COMMON_MTU_VALUES[0];
   1.944 +        SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
   1.945 +        return;
   1.946 +    }
   1.947 +
   1.948 +    for (i = 0; i < PR_ARRAY_SIZE(COMMON_MTU_VALUES); i++) {
   1.949 +        if (COMMON_MTU_VALUES[i] <= advertised) {
   1.950 +            ss->ssl3.mtu = COMMON_MTU_VALUES[i];
   1.951 +            SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
   1.952 +            return;
   1.953 +        }
   1.954 +    }
   1.955 +
   1.956 +    /* Fallback */
   1.957 +    ss->ssl3.mtu = COMMON_MTU_VALUES[PR_ARRAY_SIZE(COMMON_MTU_VALUES)-1];
   1.958 +    SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
   1.959 +}
   1.960 +
   1.961 +/* Called from ssl3_HandleHandshakeMessage() when it has deciphered a
   1.962 + * DTLS hello_verify_request
   1.963 + * Caller must hold Handshake and RecvBuf locks.
   1.964 + */
   1.965 +SECStatus
   1.966 +dtls_HandleHelloVerifyRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
   1.967 +{
   1.968 +    int                 errCode = SSL_ERROR_RX_MALFORMED_HELLO_VERIFY_REQUEST;
   1.969 +    SECStatus           rv;
   1.970 +    PRInt32             temp;
   1.971 +    SECItem             cookie = {siBuffer, NULL, 0};
   1.972 +    SSL3AlertDescription desc   = illegal_parameter;
   1.973 +
   1.974 +    SSL_TRC(3, ("%d: SSL3[%d]: handle hello_verify_request handshake",
   1.975 +        SSL_GETPID(), ss->fd));
   1.976 +    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
   1.977 +    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
   1.978 +
   1.979 +    if (ss->ssl3.hs.ws != wait_server_hello) {
   1.980 +        errCode = SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST;
   1.981 +        desc    = unexpected_message;
   1.982 +        goto alert_loser;
   1.983 +    }
   1.984 +
   1.985 +    /* The version */
   1.986 +    temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
   1.987 +    if (temp < 0) {
   1.988 +        goto loser;     /* alert has been sent */
   1.989 +    }
   1.990 +
   1.991 +    if (temp != SSL_LIBRARY_VERSION_DTLS_1_0_WIRE &&
   1.992 +        temp != SSL_LIBRARY_VERSION_DTLS_1_2_WIRE) {
   1.993 +        goto alert_loser;
   1.994 +    }
   1.995 +
   1.996 +    /* The cookie */
   1.997 +    rv = ssl3_ConsumeHandshakeVariable(ss, &cookie, 1, &b, &length);
   1.998 +    if (rv != SECSuccess) {
   1.999 +        goto loser;     /* alert has been sent */
  1.1000 +    }
  1.1001 +    if (cookie.len > DTLS_COOKIE_BYTES) {
  1.1002 +        desc = decode_error;
  1.1003 +        goto alert_loser;       /* malformed. */
  1.1004 +    }
  1.1005 +
  1.1006 +    PORT_Memcpy(ss->ssl3.hs.cookie, cookie.data, cookie.len);
  1.1007 +    ss->ssl3.hs.cookieLen = cookie.len;
  1.1008 +
  1.1009 +
  1.1010 +    ssl_GetXmitBufLock(ss);             /*******************************/
  1.1011 +
  1.1012 +    /* Now re-send the client hello */
  1.1013 +    rv = ssl3_SendClientHello(ss, PR_TRUE);
  1.1014 +
  1.1015 +    ssl_ReleaseXmitBufLock(ss);         /*******************************/
  1.1016 +
  1.1017 +    if (rv == SECSuccess)
  1.1018 +        return rv;
  1.1019 +
  1.1020 +alert_loser:
  1.1021 +    (void)SSL3_SendAlert(ss, alert_fatal, desc);
  1.1022 +
  1.1023 +loser:
  1.1024 +    errCode = ssl_MapLowLevelError(errCode);
  1.1025 +    return SECFailure;
  1.1026 +}
  1.1027 +
  1.1028 +/* Initialize the DTLS anti-replay window
  1.1029 + *
  1.1030 + * Called from:
  1.1031 + *              ssl3_SetupPendingCipherSpec()
  1.1032 + *              ssl3_InitCipherSpec()
  1.1033 + */
  1.1034 +void
  1.1035 +dtls_InitRecvdRecords(DTLSRecvdRecords *records)
  1.1036 +{
  1.1037 +    PORT_Memset(records->data, 0, sizeof(records->data));
  1.1038 +    records->left = 0;
  1.1039 +    records->right = DTLS_RECVD_RECORDS_WINDOW - 1;
  1.1040 +}
  1.1041 +
  1.1042 +/*
  1.1043 + * Has this DTLS record been received? Return values are:
  1.1044 + * -1 -- out of range to the left
  1.1045 + *  0 -- not received yet
  1.1046 + *  1 -- replay
  1.1047 + *
  1.1048 + *  Called from: dtls_HandleRecord()
  1.1049 + */
  1.1050 +int
  1.1051 +dtls_RecordGetRecvd(DTLSRecvdRecords *records, PRUint64 seq)
  1.1052 +{
  1.1053 +    PRUint64 offset;
  1.1054 +
  1.1055 +    /* Out of range to the left */
  1.1056 +    if (seq < records->left) {
  1.1057 +        return -1;
  1.1058 +    }
  1.1059 +
  1.1060 +    /* Out of range to the right; since we advance the window on
  1.1061 +     * receipt, that means that this packet has not been received
  1.1062 +     * yet */
  1.1063 +    if (seq > records->right)
  1.1064 +        return 0;
  1.1065 +
  1.1066 +    offset = seq % DTLS_RECVD_RECORDS_WINDOW;
  1.1067 +
  1.1068 +    return !!(records->data[offset / 8] & (1 << (offset % 8)));
  1.1069 +}
  1.1070 +
  1.1071 +/* Update the DTLS anti-replay window
  1.1072 + *
  1.1073 + * Called from ssl3_HandleRecord()
  1.1074 + */
  1.1075 +void
  1.1076 +dtls_RecordSetRecvd(DTLSRecvdRecords *records, PRUint64 seq)
  1.1077 +{
  1.1078 +    PRUint64 offset;
  1.1079 +
  1.1080 +    if (seq < records->left)
  1.1081 +        return;
  1.1082 +
  1.1083 +    if (seq > records->right) {
  1.1084 +        PRUint64 new_left;
  1.1085 +        PRUint64 new_right;
  1.1086 +        PRUint64 right;
  1.1087 +
  1.1088 +        /* Slide to the right; this is the tricky part
  1.1089 +         *
  1.1090 +         * 1. new_top is set to have room for seq, on the
  1.1091 +         *    next byte boundary by setting the right 8
  1.1092 +         *    bits of seq
  1.1093 +         * 2. new_left is set to compensate.
  1.1094 +         * 3. Zero all bits between top and new_top. Since
  1.1095 +         *    this is a ring, this zeroes everything as-yet
  1.1096 +         *    unseen. Because we always operate on byte
  1.1097 +         *    boundaries, we can zero one byte at a time
  1.1098 +         */
  1.1099 +        new_right = seq | 0x07;
  1.1100 +        new_left = (new_right - DTLS_RECVD_RECORDS_WINDOW) + 1;
  1.1101 +
  1.1102 +        for (right = records->right + 8; right <= new_right; right += 8) {
  1.1103 +            offset = right % DTLS_RECVD_RECORDS_WINDOW;
  1.1104 +            records->data[offset / 8] = 0;
  1.1105 +        }
  1.1106 +
  1.1107 +        records->right = new_right;
  1.1108 +        records->left = new_left;
  1.1109 +    }
  1.1110 +
  1.1111 +    offset = seq % DTLS_RECVD_RECORDS_WINDOW;
  1.1112 +
  1.1113 +    records->data[offset / 8] |= (1 << (offset % 8));
  1.1114 +}
  1.1115 +
  1.1116 +SECStatus
  1.1117 +DTLS_GetHandshakeTimeout(PRFileDesc *socket, PRIntervalTime *timeout)
  1.1118 +{
  1.1119 +    sslSocket * ss = NULL;
  1.1120 +    PRIntervalTime elapsed;
  1.1121 +    PRIntervalTime desired;
  1.1122 +
  1.1123 +    ss = ssl_FindSocket(socket);
  1.1124 +
  1.1125 +    if (!ss)
  1.1126 +        return SECFailure;
  1.1127 +
  1.1128 +    if (!IS_DTLS(ss))
  1.1129 +        return SECFailure;
  1.1130 +
  1.1131 +    if (!ss->ssl3.hs.rtTimerCb)
  1.1132 +        return SECFailure;
  1.1133 +
  1.1134 +    elapsed = PR_IntervalNow() - ss->ssl3.hs.rtTimerStarted;
  1.1135 +    desired = PR_MillisecondsToInterval(ss->ssl3.hs.rtTimeoutMs);
  1.1136 +    if (elapsed > desired) {
  1.1137 +        /* Timer expired */
  1.1138 +        *timeout = PR_INTERVAL_NO_WAIT;
  1.1139 +    } else {
  1.1140 +        *timeout = desired - elapsed;
  1.1141 +    }
  1.1142 +
  1.1143 +    return SECSuccess;
  1.1144 +}

mercurial