12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* This Source Code Form is subject to the terms of the Mozilla Public
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * License, v. 2.0. If a copy of the MPL was not distributed with this
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DTLS Protocol
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ssl.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sslimpl.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sslproto.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef PR_ARRAY_SIZE
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PR_ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SECStatus dtls_TransmitMessageFlight(sslSocket *ss);
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void dtls_RetransmitTimerExpiredCb(sslSocket *ss);
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SECStatus dtls_SendSavedWriteData(sslSocket *ss);
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* -28 adjusts for the IP/UDP header */
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const PRUint16 COMMON_MTU_VALUES[] = {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    1500 - 28,  /* Ethernet MTU */
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    1280 - 28,  /* IPv6 minimum MTU */
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    576 - 28,   /* Common assumption */
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    256 - 28    /* We're in serious trouble now */
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DTLS_COOKIE_BYTES 32
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* List copied from ssl3con.c:cipherSuites */
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ssl3CipherSuite nonDTLSSuites[] = {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef NSS_ENABLE_ECC
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TLS_ECDHE_RSA_WITH_RC4_128_SHA,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  /* NSS_ENABLE_ECC */
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TLS_DHE_DSS_WITH_RC4_128_SHA,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef NSS_ENABLE_ECC
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TLS_ECDH_RSA_WITH_RC4_128_SHA,
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  /* NSS_ENABLE_ECC */
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_RSA_WITH_RC4_128_MD5,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_RSA_WITH_RC4_128_SHA,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TLS_RSA_EXPORT1024_WITH_RC4_56_SHA,
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_RSA_EXPORT_WITH_RC4_40_MD5,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0 /* End of list marker */
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Map back and forth between TLS and DTLS versions in wire format.
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Mapping table is:
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * TLS             DTLS
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1.1 (0302)      1.0 (feff)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSL3ProtocolVersion
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dtls_TLSVersionToDTLSVersion(SSL3ProtocolVersion tlsv)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Anything other than TLS 1.1 is an error, so return
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * the invalid version ffff. */
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (tlsv != SSL_LIBRARY_VERSION_TLS_1_1)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 0xffff;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SSL_LIBRARY_VERSION_DTLS_1_0_WIRE;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Map known DTLS versions to known TLS versions.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * - Invalid versions (< 1.0) return a version of 0
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * - Versions > known return a version one higher than we know of
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to accomodate a theoretically newer version */
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSL3ProtocolVersion
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dtls_DTLSVersionToTLSVersion(SSL3ProtocolVersion dtlsv)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (MSB(dtlsv) == 0xff) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 0;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (dtlsv == SSL_LIBRARY_VERSION_DTLS_1_0_WIRE)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SSL_LIBRARY_VERSION_TLS_1_1;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Return a fictional higher version than we know of */
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SSL_LIBRARY_VERSION_TLS_1_1 + 1;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* On this socket, Disable non-DTLS cipher suites in the argument's list */
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssl3_DisableNonDTLSSuites(sslSocket * ss)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ssl3CipherSuite * suite;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (suite = nonDTLSSuites; *suite; ++suite) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	SECStatus rv = ssl3_CipherPrefSet(ss, *suite, PR_FALSE);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PORT_Assert(rv == SECSuccess); /* else is coding error */
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECSuccess;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Allocate a DTLSQueuedMessage.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called from dtls_QueueMessage()
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static DTLSQueuedMessage *
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dtls_AllocQueuedMessage(PRUint16 epoch, SSL3ContentType type,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			const unsigned char *data, PRUint32 len)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DTLSQueuedMessage *msg = NULL;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    msg = PORT_ZAlloc(sizeof(DTLSQueuedMessage));
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!msg)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return NULL;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    msg->data = PORT_Alloc(len);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!msg->data) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PORT_Free(msg);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Memcpy(msg->data, data, len);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    msg->len = len;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    msg->epoch = epoch;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    msg->type = type;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return msg;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Free a handshake message
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called from dtls_FreeHandshakeMessages()
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dtls_FreeHandshakeMessage(DTLSQueuedMessage *msg)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!msg)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_ZFree(msg->data, msg->len);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Free(msg);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Free a list of handshake messages
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called from:
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *              dtls_HandleHandshake()
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *              ssl3_DestroySSL3Info()
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dtls_FreeHandshakeMessages(PRCList *list)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRCList *cur_p;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (!PR_CLIST_IS_EMPTY(list)) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	cur_p = PR_LIST_TAIL(list);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PR_REMOVE_LINK(cur_p);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dtls_FreeHandshakeMessage((DTLSQueuedMessage *)cur_p);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Called only from ssl3_HandleRecord, for each (deciphered) DTLS record.
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * origBuf is the decrypted ssl record content and is expected to contain
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * complete handshake records
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Caller must hold the handshake and RecvBuf locks.
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Note that this code uses msg_len for two purposes:
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (1) To pass the length to ssl3_HandleHandshakeMessage()
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (2) To carry the length of a message currently being reassembled
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * However, unlike ssl3_HandleHandshake(), it is not used to carry
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the state of reassembly (i.e., whether one is in progress). That
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * is carried in recvdHighWater and recvdFragments.
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OFFSET_BYTE(o) (o/8)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OFFSET_MASK(o) (1 << (o%8))
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dtls_HandleHandshake(sslSocket *ss, sslBuffer *origBuf)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* XXX OK for now.
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * This doesn't work properly with asynchronous certificate validation.
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * because that returns a WOULDBLOCK error. The current DTLS
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * applications do not need asynchronous validation, but in the
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * future we will need to add this.
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sslBuffer buf = *origBuf;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECStatus rv = SECSuccess;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (buf.len > 0) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PRUint8 type;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PRUint32 message_length;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PRUint16 message_seq;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PRUint32 fragment_offset;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PRUint32 fragment_length;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PRUint32 offset;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (buf.len < 12) {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            rv = SECFailure;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* Parse the header */
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	type = buf.buf[0];
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        message_length = (buf.buf[1] << 16) | (buf.buf[2] << 8) | buf.buf[3];
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        message_seq = (buf.buf[4] << 8) | buf.buf[5];
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fragment_offset = (buf.buf[6] << 16) | (buf.buf[7] << 8) | buf.buf[8];
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        fragment_length = (buf.buf[9] << 16) | (buf.buf[10] << 8) | buf.buf[11];
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MAX_HANDSHAKE_MSG_LEN 0x1ffff	/* 128k - 1 */
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (message_length > MAX_HANDSHAKE_MSG_LEN) {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    (void)ssl3_DecodeError(ss);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return SECFailure;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef MAX_HANDSHAKE_MSG_LEN
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        buf.buf += 12;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        buf.len -= 12;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* This fragment must be complete */
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (buf.len < fragment_length) {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            rv = SECFailure;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* Sanity check the packet contents */
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if ((fragment_length + fragment_offset) > message_length) {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            rv = SECFailure;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            break;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* There are three ways we could not be ready for this packet.
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         *
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         * 1. It's a partial next message.
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         * 2. It's a partial or complete message beyond the next
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         * 3. It's a message we've already seen
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         *
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         * If it's the complete next message we accept it right away.
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         * This is the common case for short messages
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         */
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ((message_seq == ss->ssl3.hs.recvMessageSeq)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    && (fragment_offset == 0)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    && (fragment_length == message_length)) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /* Complete next message. Process immediately */
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ss->ssl3.hs.msg_type = (SSL3HandshakeType)type;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ss->ssl3.hs.msg_len = message_length;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /* At this point we are advancing our state machine, so
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             * we can free our last flight of messages */
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            dtls_FreeHandshakeMessages(&ss->ssl3.hs.lastMessageFlight);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ss->ssl3.hs.recvdHighWater = -1;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    dtls_CancelTimer(ss);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /* Reset the timer to the initial value if the retry counter
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     * is 0, per Sec. 4.2.4.1 */
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (ss->ssl3.hs.rtRetries == 0) {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		ss->ssl3.hs.rtTimeoutMs = INITIAL_DTLS_TIMEOUT_MS;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            rv = ssl3_HandleHandshakeMessage(ss, buf.buf, ss->ssl3.hs.msg_len);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (rv == SECFailure) {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                /* Do not attempt to process rest of messages in this record */
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (message_seq < ss->ssl3.hs.recvMessageSeq) {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		/* Case 3: we do an immediate retransmit if we're
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 * in a waiting state*/
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (ss->ssl3.hs.rtTimerCb == NULL) {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    /* Ignore */
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		} else if (ss->ssl3.hs.rtTimerCb ==
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 dtls_RetransmitTimerExpiredCb) {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    SSL_TRC(30, ("%d: SSL3[%d]: Retransmit detected",
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 SSL_GETPID(), ss->fd));
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    /* Check to see if we retransmitted recently. If so,
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     * suppress the triggered retransmit. This avoids
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     * retransmit wars after packet loss.
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     * This is not in RFC 5346 but should be
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     */
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    if ((PR_IntervalNow() - ss->ssl3.hs.rtTimerStarted) >
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			(ss->ssl3.hs.rtTimeoutMs / 4)) {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    SSL_TRC(30,
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    ("%d: SSL3[%d]: Shortcutting retransmit timer",
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            SSL_GETPID(), ss->fd));
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    /* Cancel the timer and call the CB,
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			     * which re-arms the timer */
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    dtls_CancelTimer(ss);
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    dtls_RetransmitTimerExpiredCb(ss);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    rv = SECSuccess;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    break;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			} else {
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    SSL_TRC(30,
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    ("%d: SSL3[%d]: We just retransmitted. Ignoring.",
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            SSL_GETPID(), ss->fd));
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    rv = SECSuccess;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			    break;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			}
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		} else if (ss->ssl3.hs.rtTimerCb == dtls_FinishedTimerCb) {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    /* Retransmit the messages and re-arm the timer
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     * Note that we are not backing off the timer here.
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     * The spec isn't clear and my reasoning is that this
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     * may be a re-ordered packet rather than slowness,
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     * so let's be aggressive. */
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    dtls_CancelTimer(ss);
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    rv = dtls_TransmitMessageFlight(ss);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    if (rv == SECSuccess) {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			rv = dtls_StartTimer(ss, dtls_FinishedTimerCb);
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    }
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    if (rv != SECSuccess)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			return rv;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    break;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    } else if (message_seq > ss->ssl3.hs.recvMessageSeq) {
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		/* Case 2
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 *
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 * Ignore this message. This means we don't handle out of
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 * order complete messages that well, but we're still
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 * compliant and this probably does not happen often
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 *
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 * XXX OK for now. Maybe do something smarter at some point?
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 */
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    } else {
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		/* Case 1
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 *
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 * Buffer the fragment for reassembly
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 */
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                /* Make room for the message */
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if (ss->ssl3.hs.recvdHighWater == -1) {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    PRUint32 map_length = OFFSET_BYTE(message_length) + 1;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    rv = sslBuffer_Grow(&ss->ssl3.hs.msg_body, message_length);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    if (rv != SECSuccess)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        break;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    /* Make room for the fragment map */
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    rv = sslBuffer_Grow(&ss->ssl3.hs.recvdFragments,
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        map_length);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    if (rv != SECSuccess)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        break;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    /* Reset the reassembly map */
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ss->ssl3.hs.recvdHighWater = 0;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    PORT_Memset(ss->ssl3.hs.recvdFragments.buf, 0,
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				ss->ssl3.hs.recvdFragments.space);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    ss->ssl3.hs.msg_type = (SSL3HandshakeType)type;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ss->ssl3.hs.msg_len = message_length;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                }
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                /* If we have a message length mismatch, abandon the reassembly
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 * in progress and hope that the next retransmit will give us
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 * something sane
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 */
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if (message_length != ss->ssl3.hs.msg_len) {
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ss->ssl3.hs.recvdHighWater = -1;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    PORT_SetError(SSL_ERROR_RX_MALFORMED_HANDSHAKE);
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    rv = SECFailure;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    break;
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                }
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                /* Now copy this fragment into the buffer */
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                PORT_Assert((fragment_offset + fragment_length) <=
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            ss->ssl3.hs.msg_body.space);
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                PORT_Memcpy(ss->ssl3.hs.msg_body.buf + fragment_offset,
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            buf.buf, fragment_length);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                /* This logic is a bit tricky. We have two values for
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 * reassembly state:
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 *
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 * - recvdHighWater contains the highest contiguous number of
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 *   bytes received
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 * - recvdFragments contains a bitmask of packets received
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 *   above recvdHighWater
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 *
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 * This avoids having to fill in the bitmask in the common
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 * case of adjacent fragments received in sequence
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 */
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if (fragment_offset <= ss->ssl3.hs.recvdHighWater) {
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    /* Either this is the adjacent fragment or an overlapping
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     * fragment */
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ss->ssl3.hs.recvdHighWater = fragment_offset +
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 fragment_length;
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                } else {
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    for (offset = fragment_offset;
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         offset < fragment_offset + fragment_length;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         offset++) {
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        ss->ssl3.hs.recvdFragments.buf[OFFSET_BYTE(offset)] |=
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            OFFSET_MASK(offset);
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    }
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                }
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                /* Now figure out the new high water mark if appropriate */
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                for (offset = ss->ssl3.hs.recvdHighWater;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     offset < ss->ssl3.hs.msg_len; offset++) {
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    /* Note that this loop is not efficient, since it counts
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     * bit by bit. If we have a lot of out-of-order packets,
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     * we should optimize this */
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    if (ss->ssl3.hs.recvdFragments.buf[OFFSET_BYTE(offset)] &
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        OFFSET_MASK(offset)) {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        ss->ssl3.hs.recvdHighWater++;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    } else {
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        break;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    }
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                }
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                /* If we have all the bytes, then we are good to go */
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if (ss->ssl3.hs.recvdHighWater == ss->ssl3.hs.msg_len) {
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ss->ssl3.hs.recvdHighWater = -1;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    rv = ssl3_HandleHandshakeMessage(ss,
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     ss->ssl3.hs.msg_body.buf,
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     ss->ssl3.hs.msg_len);
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    if (rv == SECFailure)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        break; /* Skip rest of record */
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    /* At this point we are advancing our state machine, so
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     * we can free our last flight of messages */
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		    dtls_FreeHandshakeMessages(&ss->ssl3.hs.lastMessageFlight);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    dtls_CancelTimer(ss);
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    /* If there have been no retries this time, reset the
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     * timer value to the default per Section 4.2.4.1 */
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    if (ss->ssl3.hs.rtRetries == 0) {
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			ss->ssl3.hs.rtTimeoutMs = INITIAL_DTLS_TIMEOUT_MS;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    }
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                }
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	buf.buf += fragment_length;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        buf.len -= fragment_length;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    origBuf->len = 0;	/* So ssl3_GatherAppDataRecord will keep looping. */
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* XXX OK for now. In future handle rv == SECWouldBlock safely in order
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * to deal with asynchronous certificate verification */
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Enqueue a message (either handshake or CCS)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called from:
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *              dtls_StageHandshakeMessage()
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *              ssl3_SendChangeCipherSpecs()
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus dtls_QueueMessage(sslSocket *ss, SSL3ContentType type,
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SSL3Opaque *pIn, PRInt32 nIn)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECStatus rv = SECSuccess;
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DTLSQueuedMessage *msg = NULL;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    msg = dtls_AllocQueuedMessage(ss->ssl3.cwSpec->epoch, type, pIn, nIn);
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!msg) {
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PORT_SetError(SEC_ERROR_NO_MEMORY);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = SECFailure;
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	PR_APPEND_LINK(&msg->link, &ss->ssl3.hs.lastMessageFlight);
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Add DTLS handshake message to the pending queue
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Empty the sendBuf buffer.
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This function returns SECSuccess or SECFailure, never SECWouldBlock.
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Always set sendBuf.len to 0, even when returning SECFailure.
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called from:
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *              ssl3_AppendHandshakeHeader()
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *              dtls_FlushHandshake()
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dtls_StageHandshakeMessage(sslSocket *ss)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECStatus rv = SECSuccess;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* This function is sometimes called when no data is actually to
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * be staged, so just return SECSuccess. */
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ss->sec.ci.sendBuf.buf || !ss->sec.ci.sendBuf.len)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return rv;
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = dtls_QueueMessage(ss, content_handshake,
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           ss->sec.ci.sendBuf.buf, ss->sec.ci.sendBuf.len);
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Whether we succeeded or failed, toss the old handshake data. */
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ss->sec.ci.sendBuf.len = 0;
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Enqueue the handshake message in sendBuf (if any) and then
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * transmit the resulting flight of handshake messages.
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called from:
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *              ssl3_FlushHandshake()
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dtls_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECStatus rv = SECSuccess;
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = dtls_StageHandshakeMessage(ss);
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return rv;
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!(flags & ssl_SEND_FLAG_FORCE_INTO_BUFFER)) {
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = dtls_TransmitMessageFlight(ss);
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (rv != SECSuccess)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return rv;
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (!(flags & ssl_SEND_FLAG_NO_RETRANSMIT)) {
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ss->ssl3.hs.rtRetries = 0;
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    rv = dtls_StartTimer(ss, dtls_RetransmitTimerExpiredCb);
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* The callback for when the retransmit timer expires
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called from:
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *              dtls_CheckTimer()
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *              dtls_HandleHandshake()
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dtls_RetransmitTimerExpiredCb(sslSocket *ss)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECStatus rv = SECFailure;
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ss->ssl3.hs.rtRetries++;
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!(ss->ssl3.hs.rtRetries % 3)) {
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* If one of the messages was potentially greater than > MTU,
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * then downgrade. Do this every time we have retransmitted a
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * message twice, per RFC 6347 Sec. 4.1.1 */
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dtls_SetMTU(ss, ss->ssl3.hs.maxMessageSent - 1);
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = dtls_TransmitMessageFlight(ss);
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == SECSuccess) {
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Re-arm the timer */
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = dtls_RestartTimer(ss, PR_TRUE, dtls_RetransmitTimerExpiredCb);
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == SECFailure) {
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* XXX OK for now. In future maybe signal the stack that we couldn't
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * transmit. For now, let the read handle any real network errors */
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Transmit a flight of handshake messages, stuffing them
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * into as few records as seems reasonable
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called from:
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *             dtls_FlushHandshake()
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *             dtls_RetransmitTimerExpiredCb()
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SECStatus
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dtls_TransmitMessageFlight(sslSocket *ss)
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECStatus rv = SECSuccess;
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRCList *msg_p;
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRUint16 room_left = ss->ssl3.mtu;
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRInt32 sent;
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_GetXmitBufLock(ss);
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_GetSpecReadLock(ss);
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* DTLS does not buffer its handshake messages in
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * ss->pendingBuf, but rather in the lastMessageFlight
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * structure. This is just a sanity check that
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * some programming error hasn't inadvertantly
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * stuffed something in ss->pendingBuf
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Assert(!ss->pendingBuf.len);
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (msg_p = PR_LIST_HEAD(&ss->ssl3.hs.lastMessageFlight);
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	 msg_p != &ss->ssl3.hs.lastMessageFlight;
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 msg_p = PR_NEXT_LINK(msg_p)) {
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DTLSQueuedMessage *msg = (DTLSQueuedMessage *)msg_p;
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* The logic here is:
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         *
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * 1. If this is a message that will not fit into the remaining
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 *    space, then flush.
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * 2. If the message will now fit into the remaining space,
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         *    encrypt, buffer, and loop.
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         * 3. If the message will not fit, then fragment.
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         *
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * At the end of the function, flush.
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         */
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ((msg->len + SSL3_BUFFER_FUDGE) > room_left) {
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /* The message will not fit into the remaining space, so flush */
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    rv = dtls_SendSavedWriteData(ss);
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    if (rv != SECSuccess)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		break;
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            room_left = ss->ssl3.mtu;
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if ((msg->len + SSL3_BUFFER_FUDGE) <= room_left) {
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /* The message will fit, so encrypt and then continue with the
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     * next packet */
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            sent = ssl3_SendRecord(ss, msg->epoch, msg->type,
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   msg->data, msg->len,
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   ssl_SEND_FLAG_FORCE_INTO_BUFFER |
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   ssl_SEND_FLAG_USE_EPOCH);
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if (sent != msg->len) {
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		rv = SECFailure;
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (sent != -1) {
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                break;
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    }
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            room_left = ss->ssl3.mtu - ss->pendingBuf.len;
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /* The message will not fit, so fragment.
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             *
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     * XXX OK for now. Arrange to coalesce the last fragment
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     * of this message with the next message if possible.
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     * That would be more efficient.
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     */
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            PRUint32 fragment_offset = 0;
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            unsigned char fragment[DTLS_MAX_MTU]; /* >= than largest
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   * plausible MTU */
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /* Assert that we have already flushed */
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    PORT_Assert(room_left == ss->ssl3.mtu);
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            /* Case 3: We now need to fragment this message
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             * DTLS only supports fragmenting handshaking messages */
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            PORT_Assert(msg->type == content_handshake);
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    /* The headers consume 12 bytes so the smalles possible
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     *  message (i.e., an empty one) is 12 bytes
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	     */
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    PORT_Assert(msg->len >= 12);
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            while ((fragment_offset + 12) < msg->len) {
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                PRUint32 fragment_len;
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                const unsigned char *content = msg->data + 12;
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                PRUint32 content_len = msg->len - 12;
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		/* The reason we use 8 here is that that's the length of
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 * the new DTLS data that we add to the header */
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                fragment_len = PR_MIN(room_left - (SSL3_BUFFER_FUDGE + 8),
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      content_len - fragment_offset);
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		PORT_Assert(fragment_len < DTLS_MAX_MTU - 12);
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		/* Make totally sure that we are within the buffer.
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 * Note that the only way that fragment len could get
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 * adjusted here is if
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 *
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 * (a) we are in release mode so the PORT_Assert is compiled out
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 * (b) either the MTU table is inconsistent with DTLS_MAX_MTU
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 * or ss->ssl3.mtu has become corrupt.
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 */
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		fragment_len = PR_MIN(fragment_len, DTLS_MAX_MTU - 12);
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                /* Construct an appropriate-sized fragment */
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                /* Type, length, sequence */
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                PORT_Memcpy(fragment, msg->data, 6);
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                /* Offset */
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                fragment[6] = (fragment_offset >> 16) & 0xff;
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                fragment[7] = (fragment_offset >> 8) & 0xff;
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                fragment[8] = (fragment_offset) & 0xff;
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                /* Fragment length */
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                fragment[9] = (fragment_len >> 16) & 0xff;
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                fragment[10] = (fragment_len >> 8) & 0xff;
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                fragment[11] = (fragment_len) & 0xff;
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                PORT_Memcpy(fragment + 12, content + fragment_offset,
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            fragment_len);
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                /*
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 *  Send the record. We do this in two stages
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 * 1. Encrypt
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		 */
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                sent = ssl3_SendRecord(ss, msg->epoch, msg->type,
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       fragment, fragment_len + 12,
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       ssl_SEND_FLAG_FORCE_INTO_BUFFER |
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				       ssl_SEND_FLAG_USE_EPOCH);
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if (sent != (fragment_len + 12)) {
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    rv = SECFailure;
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    if (sent != -1) {
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    }
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    break;
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		}
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		/* 2. Flush */
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		rv = dtls_SendSavedWriteData(ss);
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		if (rv != SECSuccess)
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		    break;
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                fragment_offset += fragment_len;
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Finally, we need to flush */
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == SECSuccess)
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rv = dtls_SendSavedWriteData(ss);
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Give up the locks */
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_ReleaseSpecReadLock(ss);
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_ReleaseXmitBufLock(ss);
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Flush the data in the pendingBuf and update the max message sent
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * so we can adjust the MTU estimate if we need to.
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Wrapper for ssl_SendSavedWriteData.
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called from dtls_TransmitMessageFlight()
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus dtls_SendSavedWriteData(sslSocket *ss)
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRInt32 sent;
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sent = ssl_SendSavedWriteData(ss);
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sent < 0)
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return SECFailure;
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* We should always have complete writes b/c datagram sockets
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * don't really block */
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ss->pendingBuf.len > 0) {
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ssl_MapLowLevelError(SSL_ERROR_SOCKET_WRITE_FAILURE);
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    	return SECFailure;
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Update the largest message sent so we can adjust the MTU
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * estimate if necessary */
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sent > ss->ssl3.hs.maxMessageSent)
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ss->ssl3.hs.maxMessageSent = sent;
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECSuccess;
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Compress, MAC, encrypt a DTLS record. Allows specification of
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the epoch using epoch value. If use_epoch is PR_TRUE then
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * we use the provided epoch. If use_epoch is PR_FALSE then
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * whatever the current value is in effect is used.
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called from ssl3_SendRecord()
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dtls_CompressMACEncryptRecord(sslSocket *        ss,
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              DTLSEpoch          epoch,
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			      PRBool             use_epoch,
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              SSL3ContentType    type,
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		              const SSL3Opaque * pIn,
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		              PRUint32           contentLen,
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			      sslBuffer        * wrBuf)
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECStatus rv = SECFailure;
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl3CipherSpec *          cwSpec;
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_GetSpecReadLock(ss);	/********************************/
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* The reason for this switch-hitting code is that we might have
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * a flight of records spanning an epoch boundary, e.g.,
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * ClientKeyExchange (epoch = 0)
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * ChangeCipherSpec (epoch = 0)
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Finished (epoch = 1)
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     *
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * Thus, each record needs a different cipher spec. The information
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * about which epoch to use is carried with the record.
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     */
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (use_epoch) {
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ss->ssl3.cwSpec->epoch == epoch)
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    cwSpec = ss->ssl3.cwSpec;
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	else if (ss->ssl3.pwSpec->epoch == epoch)
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    cwSpec = ss->ssl3.pwSpec;
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	else
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    cwSpec = NULL;
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	cwSpec = ss->ssl3.cwSpec;
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (cwSpec) {
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = ssl3_CompressMACEncryptRecord(cwSpec, ss->sec.isServer, PR_TRUE,
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					   PR_FALSE, type, pIn, contentLen,
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					   wrBuf);
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        PR_NOT_REACHED("Couldn't find a cipher spec matching epoch");
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_ReleaseSpecReadLock(ss); /************************************/
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Start a timer
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called from:
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *             dtls_HandleHandshake()
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *             dtls_FlushHAndshake()
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *             dtls_RestartTimer()
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dtls_StartTimer(sslSocket *ss, DTLSTimerCb cb)
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Assert(ss->ssl3.hs.rtTimerCb == NULL);
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ss->ssl3.hs.rtTimerStarted = PR_IntervalNow();
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ss->ssl3.hs.rtTimerCb = cb;
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECSuccess;
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Restart a timer with optional backoff
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called from dtls_RetransmitTimerExpiredCb()
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dtls_RestartTimer(sslSocket *ss, PRBool backoff, DTLSTimerCb cb)
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (backoff) {
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ss->ssl3.hs.rtTimeoutMs *= 2;
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (ss->ssl3.hs.rtTimeoutMs > MAX_DTLS_TIMEOUT_MS)
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ss->ssl3.hs.rtTimeoutMs = MAX_DTLS_TIMEOUT_MS;
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return dtls_StartTimer(ss, cb);
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Cancel a pending timer
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called from:
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *              dtls_HandleHandshake()
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *              dtls_CheckTimer()
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dtls_CancelTimer(sslSocket *ss)
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ss->ssl3.hs.rtTimerCb = NULL;
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Check the pending timer and fire the callback if it expired
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called from ssl3_GatherCompleteHandshake()
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dtls_CheckTimer(sslSocket *ss)
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ss->ssl3.hs.rtTimerCb)
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((PR_IntervalNow() - ss->ssl3.hs.rtTimerStarted) >
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PR_MillisecondsToInterval(ss->ssl3.hs.rtTimeoutMs)) {
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Timer has expired */
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	DTLSTimerCb cb = ss->ssl3.hs.rtTimerCb;
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Cancel the timer so that we can call the CB safely */
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	dtls_CancelTimer(ss);
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Now call the CB */
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	cb(ss);
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* The callback to fire when the holddown timer for the Finished
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * message expires and we can delete it
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called from dtls_CheckTimer()
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dtls_FinishedTimerCb(sslSocket *ss)
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_FALSE);
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Cancel the Finished hold-down timer and destroy the
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * pending cipher spec. Note that this means that
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * successive rehandshakes will fail if the Finished is
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * lost.
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * XXX OK for now. Figure out how to handle the combination
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of Finished lost and rehandshake
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dtls_RehandshakeCleanup(sslSocket *ss)
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dtls_CancelTimer(ss);
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_FALSE);
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ss->ssl3.hs.sendMessageSeq = 0;
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ss->ssl3.hs.recvMessageSeq = 0;
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Set the MTU to the next step less than or equal to the
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * advertised value. Also used to downgrade the MTU by
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * doing dtls_SetMTU(ss, biggest packet set).
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Passing 0 means set this to the largest MTU known
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (effectively resetting the PMTU backoff value).
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called by:
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *            ssl3_InitState()
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *            dtls_RetransmitTimerExpiredCb()
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dtls_SetMTU(sslSocket *ss, PRUint16 advertised)
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i;
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (advertised == 0) {
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	ss->ssl3.mtu = COMMON_MTU_VALUES[0];
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < PR_ARRAY_SIZE(COMMON_MTU_VALUES); i++) {
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (COMMON_MTU_VALUES[i] <= advertised) {
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    ss->ssl3.mtu = COMMON_MTU_VALUES[i];
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return;
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Fallback */
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ss->ssl3.mtu = COMMON_MTU_VALUES[PR_ARRAY_SIZE(COMMON_MTU_VALUES)-1];
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_TRC(30, ("Resetting MTU to %d", ss->ssl3.mtu));
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Called from ssl3_HandleHandshakeMessage() when it has deciphered a
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DTLS hello_verify_request
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Caller must hold Handshake and RecvBuf locks.
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dtls_HandleHelloVerifyRequest(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int                 errCode	= SSL_ERROR_RX_MALFORMED_HELLO_VERIFY_REQUEST;
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECStatus           rv;
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRInt32             temp;
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SECItem             cookie = {siBuffer, NULL, 0};
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL3AlertDescription desc   = illegal_parameter;
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_TRC(3, ("%d: SSL3[%d]: handle hello_verify_request handshake",
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    	SSL_GETPID(), ss->fd));
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ss->ssl3.hs.ws != wait_server_hello) {
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        errCode = SSL_ERROR_RX_UNEXPECTED_HELLO_VERIFY_REQUEST;
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	desc    = unexpected_message;
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	goto alert_loser;
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* The version */
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (temp < 0) {
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    	goto loser; 	/* alert has been sent */
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (temp != SSL_LIBRARY_VERSION_DTLS_1_0_WIRE) {
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Note: this will need adjustment for DTLS 1.2 per Section 4.2.1 */
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	goto alert_loser;
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* The cookie */
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ssl3_ConsumeHandshakeVariable(ss, &cookie, 1, &b, &length);
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != SECSuccess) {
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    	goto loser; 	/* alert has been sent */
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (cookie.len > DTLS_COOKIE_BYTES) {
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	desc = decode_error;
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	goto alert_loser;	/* malformed. */
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Memcpy(ss->ssl3.hs.cookie, cookie.data, cookie.len);
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ss->ssl3.hs.cookieLen = cookie.len;
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_GetXmitBufLock(ss);		/*******************************/
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Now re-send the client hello */
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ssl3_SendClientHello(ss, PR_TRUE);
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_ReleaseXmitBufLock(ss);		/*******************************/
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == SECSuccess)
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return rv;
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)alert_loser:
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (void)SSL3_SendAlert(ss, alert_fatal, desc);
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)loser:
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    errCode = ssl_MapLowLevelError(errCode);
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECFailure;
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Initialize the DTLS anti-replay window
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called from:
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *              ssl3_SetupPendingCipherSpec()
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *              ssl3_InitCipherSpec()
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dtls_InitRecvdRecords(DTLSRecvdRecords *records)
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PORT_Memset(records->data, 0, sizeof(records->data));
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    records->left = 0;
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    records->right = DTLS_RECVD_RECORDS_WINDOW - 1;
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Has this DTLS record been received? Return values are:
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * -1 -- out of range to the left
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  0 -- not received yet
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  1 -- replay
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  Called from: dtls_HandleRecord()
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dtls_RecordGetRecvd(DTLSRecvdRecords *records, PRUint64 seq)
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRUint64 offset;
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Out of range to the left */
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (seq < records->left) {
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return -1;
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Out of range to the right; since we advance the window on
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * receipt, that means that this packet has not been received
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * yet */
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (seq > records->right)
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return 0;
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    offset = seq % DTLS_RECVD_RECORDS_WINDOW;
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return !!(records->data[offset / 8] & (1 << (offset % 8)));
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Update the DTLS anti-replay window
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Called from ssl3_HandleRecord()
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)dtls_RecordSetRecvd(DTLSRecvdRecords *records, PRUint64 seq)
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRUint64 offset;
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (seq < records->left)
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (seq > records->right) {
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PRUint64 new_left;
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PRUint64 new_right;
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	PRUint64 right;
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	/* Slide to the right; this is the tricky part
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         *
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 * 1. new_top is set to have room for seq, on the
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 *    next byte boundary by setting the right 8
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 *    bits of seq
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         * 2. new_left is set to compensate.
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         * 3. Zero all bits between top and new_top. Since
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         *    this is a ring, this zeroes everything as-yet
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 *    unseen. Because we always operate on byte
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 *    boundaries, we can zero one byte at a time
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 */
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	new_right = seq | 0x07;
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	new_left = (new_right - DTLS_RECVD_RECORDS_WINDOW) + 1;
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	for (right = records->right + 8; right <= new_right; right += 8) {
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    offset = right % DTLS_RECVD_RECORDS_WINDOW;
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    records->data[offset / 8] = 0;
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	}
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	records->right = new_right;
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	records->left = new_left;
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    offset = seq % DTLS_RECVD_RECORDS_WINDOW;
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    records->data[offset / 8] |= (1 << (offset % 8));
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DTLS_GetHandshakeTimeout(PRFileDesc *socket, PRIntervalTime *timeout)
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sslSocket * ss = NULL;
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRIntervalTime elapsed;
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRIntervalTime desired;
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ss = ssl_FindSocket(socket);
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ss)
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SECFailure;
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!IS_DTLS(ss))
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SECFailure;
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ss->ssl3.hs.rtTimerCb)
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return SECFailure;
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    elapsed = PR_IntervalNow() - ss->ssl3.hs.rtTimerStarted;
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    desired = PR_MillisecondsToInterval(ss->ssl3.hs.rtTimeoutMs);
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (elapsed > desired) {
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        /* Timer expired */
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *timeout = PR_INTERVAL_NO_WAIT;
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *timeout = desired - elapsed;
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return SECSuccess;
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1133