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