1*ae0a2582Sjsing /* $OpenBSD: d1_lib.c,v 1.65 2024/07/23 14:40:53 jsing Exp $ */ 25650a0e1Sdjm /* 35650a0e1Sdjm * DTLS implementation written by Nagendra Modadugu 45650a0e1Sdjm * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. 55650a0e1Sdjm */ 65650a0e1Sdjm /* ==================================================================== 75650a0e1Sdjm * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved. 85650a0e1Sdjm * 95650a0e1Sdjm * Redistribution and use in source and binary forms, with or without 105650a0e1Sdjm * modification, are permitted provided that the following conditions 115650a0e1Sdjm * are met: 125650a0e1Sdjm * 135650a0e1Sdjm * 1. Redistributions of source code must retain the above copyright 145650a0e1Sdjm * notice, this list of conditions and the following disclaimer. 155650a0e1Sdjm * 165650a0e1Sdjm * 2. Redistributions in binary form must reproduce the above copyright 175650a0e1Sdjm * notice, this list of conditions and the following disclaimer in 185650a0e1Sdjm * the documentation and/or other materials provided with the 195650a0e1Sdjm * distribution. 205650a0e1Sdjm * 215650a0e1Sdjm * 3. All advertising materials mentioning features or use of this 225650a0e1Sdjm * software must display the following acknowledgment: 235650a0e1Sdjm * "This product includes software developed by the OpenSSL Project 245650a0e1Sdjm * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 255650a0e1Sdjm * 265650a0e1Sdjm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 275650a0e1Sdjm * endorse or promote products derived from this software without 285650a0e1Sdjm * prior written permission. For written permission, please contact 295650a0e1Sdjm * openssl-core@OpenSSL.org. 305650a0e1Sdjm * 315650a0e1Sdjm * 5. Products derived from this software may not be called "OpenSSL" 325650a0e1Sdjm * nor may "OpenSSL" appear in their names without prior written 335650a0e1Sdjm * permission of the OpenSSL Project. 345650a0e1Sdjm * 355650a0e1Sdjm * 6. Redistributions of any form whatsoever must retain the following 365650a0e1Sdjm * acknowledgment: 375650a0e1Sdjm * "This product includes software developed by the OpenSSL Project 385650a0e1Sdjm * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 395650a0e1Sdjm * 405650a0e1Sdjm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 415650a0e1Sdjm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 425650a0e1Sdjm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 435650a0e1Sdjm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 445650a0e1Sdjm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 455650a0e1Sdjm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 465650a0e1Sdjm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 475650a0e1Sdjm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 485650a0e1Sdjm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 495650a0e1Sdjm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 505650a0e1Sdjm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 515650a0e1Sdjm * OF THE POSSIBILITY OF SUCH DAMAGE. 525650a0e1Sdjm * ==================================================================== 535650a0e1Sdjm * 545650a0e1Sdjm * This product includes cryptographic software written by Eric Young 555650a0e1Sdjm * (eay@cryptsoft.com). This product includes software written by Tim 565650a0e1Sdjm * Hudson (tjh@cryptsoft.com). 575650a0e1Sdjm * 585650a0e1Sdjm */ 595650a0e1Sdjm 60c6f33ed0Sderaadt #include <sys/types.h> 610579501cSmpi #include <sys/socket.h> 62217902d8Sbcook #include <sys/time.h> 630579501cSmpi 640579501cSmpi #include <netinet/in.h> 650579501cSmpi 665650a0e1Sdjm #include <stdio.h> 67c5899dbcSjsing 685650a0e1Sdjm #include <openssl/objects.h> 6946859c4aSjsing 70c9675a23Stb #include "dtls_local.h" 7146859c4aSjsing #include "pqueue.h" 72c9675a23Stb #include "ssl_local.h" 735650a0e1Sdjm 7455a1a82cSjsing void dtls1_hm_fragment_free(hm_fragment *frag); 7555a1a82cSjsing 76fca6a006Sguenther static int dtls1_listen(SSL *s, struct sockaddr *client); 775650a0e1Sdjm 784a47b859Sjsing int 794a47b859Sjsing dtls1_new(SSL *s) 805650a0e1Sdjm { 814a47b859Sjsing if (!ssl3_new(s)) 829f8f562aSjsing goto err; 835650a0e1Sdjm 849f8f562aSjsing if ((s->d1 = calloc(1, sizeof(*s->d1))) == NULL) 859f8f562aSjsing goto err; 865650a0e1Sdjm 87f19d9718Sjsing if ((s->d1->unprocessed_rcds.q = pqueue_new()) == NULL) 889f8f562aSjsing goto err; 89f19d9718Sjsing if ((s->d1->buffered_messages = pqueue_new()) == NULL) 909f8f562aSjsing goto err; 919f8f562aSjsing if ((s->d1->sent_messages = pqueue_new()) == NULL) 929f8f562aSjsing goto err; 93f19d9718Sjsing if ((s->d1->buffered_app_data.q = pqueue_new()) == NULL) 949f8f562aSjsing goto err; 955650a0e1Sdjm 969f8f562aSjsing if (s->server) 97f19d9718Sjsing s->d1->cookie_len = sizeof(s->d1->cookie); 985650a0e1Sdjm 996ba40c14Sjsing s->method->ssl_clear(s); 1005650a0e1Sdjm return (1); 1019f8f562aSjsing 1029f8f562aSjsing err: 1039f8f562aSjsing dtls1_free(s); 1049f8f562aSjsing return (0); 1055650a0e1Sdjm } 1065650a0e1Sdjm 1074a47b859Sjsing static void 108ee4250f6Sjsing dtls1_drain_rcontents(pqueue queue) 109ee4250f6Sjsing { 110ee4250f6Sjsing DTLS1_RCONTENT_DATA_INTERNAL *rdata; 111ee4250f6Sjsing pitem *item; 112ee4250f6Sjsing 113ee4250f6Sjsing if (queue == NULL) 114ee4250f6Sjsing return; 115ee4250f6Sjsing 116ee4250f6Sjsing while ((item = pqueue_pop(queue)) != NULL) { 117ee4250f6Sjsing rdata = (DTLS1_RCONTENT_DATA_INTERNAL *)item->data; 118ee4250f6Sjsing tls_content_free(rdata->rcontent); 119ee4250f6Sjsing free(item->data); 120ee4250f6Sjsing pitem_free(item); 121ee4250f6Sjsing } 122ee4250f6Sjsing } 123ee4250f6Sjsing 124ee4250f6Sjsing static void 1259215d666Stb dtls1_drain_records(pqueue queue) 1265650a0e1Sdjm { 1279215d666Stb pitem *item; 1286182911eSjsing DTLS1_RECORD_DATA_INTERNAL *rdata; 1295650a0e1Sdjm 1309215d666Stb if (queue == NULL) 1319215d666Stb return; 1329215d666Stb 1339215d666Stb while ((item = pqueue_pop(queue)) != NULL) { 1346182911eSjsing rdata = (DTLS1_RECORD_DATA_INTERNAL *)item->data; 135435f94b7Sjsing ssl3_release_buffer(&rdata->rbuf); 1366f3a6cb1Sbeck free(item->data); 1375650a0e1Sdjm pitem_free(item); 1385650a0e1Sdjm } 1395650a0e1Sdjm } 1405650a0e1Sdjm 1419215d666Stb static void 1429215d666Stb dtls1_drain_fragments(pqueue queue) 1439215d666Stb { 1449215d666Stb pitem *item; 1459215d666Stb 1469215d666Stb if (queue == NULL) 1479215d666Stb return; 1489215d666Stb 1499215d666Stb while ((item = pqueue_pop(queue)) != NULL) { 15055a1a82cSjsing dtls1_hm_fragment_free(item->data); 1515650a0e1Sdjm pitem_free(item); 1525650a0e1Sdjm } 1535650a0e1Sdjm } 1540579501cSmpi 1559215d666Stb static void 1569215d666Stb dtls1_clear_queues(SSL *s) 1579215d666Stb { 158f19d9718Sjsing dtls1_drain_records(s->d1->unprocessed_rcds.q); 159f19d9718Sjsing dtls1_drain_fragments(s->d1->buffered_messages); 1609215d666Stb dtls1_drain_fragments(s->d1->sent_messages); 161ee4250f6Sjsing dtls1_drain_rcontents(s->d1->buffered_app_data.q); 1620579501cSmpi } 1630579501cSmpi 1644a47b859Sjsing void 1654a47b859Sjsing dtls1_free(SSL *s) 1660579501cSmpi { 167dd39d9ddSdoug if (s == NULL) 168dd39d9ddSdoug return; 169dd39d9ddSdoug 1700579501cSmpi ssl3_free(s); 1710579501cSmpi 172ea21f82aStb if (s->d1 == NULL) 173ea21f82aStb return; 174ea21f82aStb 1750579501cSmpi dtls1_clear_queues(s); 1760579501cSmpi 177f19d9718Sjsing pqueue_free(s->d1->unprocessed_rcds.q); 178f19d9718Sjsing pqueue_free(s->d1->buffered_messages); 1799a0dbe41Sdjm pqueue_free(s->d1->sent_messages); 180f19d9718Sjsing pqueue_free(s->d1->buffered_app_data.q); 1815650a0e1Sdjm 1828f2be08bSjsing freezero(s->d1, sizeof(*s->d1)); 1830579501cSmpi s->d1 = NULL; 1845650a0e1Sdjm } 1855650a0e1Sdjm 1864a47b859Sjsing void 1874a47b859Sjsing dtls1_clear(SSL *s) 1885650a0e1Sdjm { 1890579501cSmpi pqueue unprocessed_rcds; 1900579501cSmpi pqueue buffered_messages; 1910579501cSmpi pqueue sent_messages; 1920579501cSmpi pqueue buffered_app_data; 1930579501cSmpi unsigned int mtu; 1940579501cSmpi 1954a47b859Sjsing if (s->d1) { 196f19d9718Sjsing unprocessed_rcds = s->d1->unprocessed_rcds.q; 197f19d9718Sjsing buffered_messages = s->d1->buffered_messages; 1980579501cSmpi sent_messages = s->d1->sent_messages; 199f19d9718Sjsing buffered_app_data = s->d1->buffered_app_data.q; 200f19d9718Sjsing mtu = s->d1->mtu; 2010579501cSmpi 2020579501cSmpi dtls1_clear_queues(s); 2030579501cSmpi 2048462f404Sjsing memset(s->d1, 0, sizeof(*s->d1)); 2050579501cSmpi 206f19d9718Sjsing s->d1->unprocessed_rcds.epoch = 2076f7f653bSjsing tls12_record_layer_read_epoch(s->rl) + 1; 20812a1eb2dSjsing 2094a47b859Sjsing if (s->server) { 210f19d9718Sjsing s->d1->cookie_len = sizeof(s->d1->cookie); 2110579501cSmpi } 2120579501cSmpi 2134a47b859Sjsing if (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU) { 214f19d9718Sjsing s->d1->mtu = mtu; 2150579501cSmpi } 2160579501cSmpi 217f19d9718Sjsing s->d1->unprocessed_rcds.q = unprocessed_rcds; 218f19d9718Sjsing s->d1->buffered_messages = buffered_messages; 2190579501cSmpi s->d1->sent_messages = sent_messages; 220f19d9718Sjsing s->d1->buffered_app_data.q = buffered_app_data; 2210579501cSmpi } 2220579501cSmpi 2235650a0e1Sdjm ssl3_clear(s); 2247489cb3dSjsing 2255650a0e1Sdjm s->version = DTLS1_VERSION; 2265650a0e1Sdjm } 2275650a0e1Sdjm 2284a47b859Sjsing long 2294a47b859Sjsing dtls1_ctrl(SSL *s, int cmd, long larg, void *parg) 2300579501cSmpi { 2310579501cSmpi int ret = 0; 2320579501cSmpi 2334a47b859Sjsing switch (cmd) { 2340579501cSmpi case DTLS_CTRL_GET_TIMEOUT: 2354a47b859Sjsing if (dtls1_get_timeout(s, (struct timeval*) parg) != NULL) { 2360579501cSmpi ret = 1; 2370579501cSmpi } 2380579501cSmpi break; 2390579501cSmpi case DTLS_CTRL_HANDLE_TIMEOUT: 2400579501cSmpi ret = dtls1_handle_timeout(s); 2410579501cSmpi break; 2420579501cSmpi case DTLS_CTRL_LISTEN: 2430579501cSmpi ret = dtls1_listen(s, parg); 2440579501cSmpi break; 2450579501cSmpi 2460579501cSmpi default: 2470579501cSmpi ret = ssl3_ctrl(s, cmd, larg, parg); 2480579501cSmpi break; 2490579501cSmpi } 2500579501cSmpi return (ret); 2510579501cSmpi } 2520579501cSmpi 2534a47b859Sjsing void 2544a47b859Sjsing dtls1_start_timer(SSL *s) 2550579501cSmpi { 2560579501cSmpi 2570579501cSmpi /* If timer is not set, initialize duration with 1 second */ 2584a47b859Sjsing if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) { 2590579501cSmpi s->d1->timeout_duration = 1; 2600579501cSmpi } 2610579501cSmpi 2620579501cSmpi /* Set timeout to current time */ 26333e311cfSderaadt gettimeofday(&(s->d1->next_timeout), NULL); 2640579501cSmpi 2650579501cSmpi /* Add duration to current time */ 2660579501cSmpi s->d1->next_timeout.tv_sec += s->d1->timeout_duration; 267b09c1e06Sderaadt BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, 268f7271532Sbeck &s->d1->next_timeout); 2690579501cSmpi } 2700579501cSmpi 2714a47b859Sjsing struct timeval* 272b09c1e06Sderaadt dtls1_get_timeout(SSL *s, struct timeval* timeleft) 273b09c1e06Sderaadt { 2740579501cSmpi struct timeval timenow; 2750579501cSmpi 2760579501cSmpi /* If no timeout is set, just return NULL */ 2774a47b859Sjsing if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) { 2780579501cSmpi return NULL; 2790579501cSmpi } 2800579501cSmpi 2810579501cSmpi /* Get current time */ 28233e311cfSderaadt gettimeofday(&timenow, NULL); 2830579501cSmpi 2840579501cSmpi /* If timer already expired, set remaining time to 0 */ 2850579501cSmpi if (s->d1->next_timeout.tv_sec < timenow.tv_sec || 2860579501cSmpi (s->d1->next_timeout.tv_sec == timenow.tv_sec && 2874a47b859Sjsing s->d1->next_timeout.tv_usec <= timenow.tv_usec)) { 2880579501cSmpi memset(timeleft, 0, sizeof(struct timeval)); 2890579501cSmpi return timeleft; 2900579501cSmpi } 2910579501cSmpi 2920579501cSmpi /* Calculate time left until timer expires */ 2930579501cSmpi memcpy(timeleft, &(s->d1->next_timeout), sizeof(struct timeval)); 2940579501cSmpi timeleft->tv_sec -= timenow.tv_sec; 2950579501cSmpi timeleft->tv_usec -= timenow.tv_usec; 2964a47b859Sjsing if (timeleft->tv_usec < 0) { 2970579501cSmpi timeleft->tv_sec--; 2980579501cSmpi timeleft->tv_usec += 1000000; 2990579501cSmpi } 3000579501cSmpi 3010579501cSmpi /* If remaining time is less than 15 ms, set it to 0 3020579501cSmpi * to prevent issues because of small devergences with 3030579501cSmpi * socket timeouts. 3040579501cSmpi */ 3054a47b859Sjsing if (timeleft->tv_sec == 0 && timeleft->tv_usec < 15000) { 3060579501cSmpi memset(timeleft, 0, sizeof(struct timeval)); 3070579501cSmpi } 3080579501cSmpi 3090579501cSmpi 3100579501cSmpi return timeleft; 3110579501cSmpi } 3120579501cSmpi 3134a47b859Sjsing int 3144a47b859Sjsing dtls1_is_timer_expired(SSL *s) 3150579501cSmpi { 3160579501cSmpi struct timeval timeleft; 3170579501cSmpi 3180579501cSmpi /* Get time left until timeout, return false if no timer running */ 3194a47b859Sjsing if (dtls1_get_timeout(s, &timeleft) == NULL) { 3200579501cSmpi return 0; 3210579501cSmpi } 3220579501cSmpi 3230579501cSmpi /* Return false if timer is not expired yet */ 3244a47b859Sjsing if (timeleft.tv_sec > 0 || timeleft.tv_usec > 0) { 3250579501cSmpi return 0; 3260579501cSmpi } 3270579501cSmpi 3280579501cSmpi /* Timer expired, so return true */ 3290579501cSmpi return 1; 3300579501cSmpi } 3310579501cSmpi 3324a47b859Sjsing void 3334a47b859Sjsing dtls1_double_timeout(SSL *s) 3340579501cSmpi { 3350579501cSmpi s->d1->timeout_duration *= 2; 3360579501cSmpi if (s->d1->timeout_duration > 60) 3370579501cSmpi s->d1->timeout_duration = 60; 3380579501cSmpi dtls1_start_timer(s); 3390579501cSmpi } 3400579501cSmpi 3414a47b859Sjsing void 3424a47b859Sjsing dtls1_stop_timer(SSL *s) 3430579501cSmpi { 3440579501cSmpi /* Reset everything */ 345f19d9718Sjsing memset(&(s->d1->timeout), 0, sizeof(struct dtls1_timeout_st)); 3460579501cSmpi memset(&(s->d1->next_timeout), 0, sizeof(struct timeval)); 3470579501cSmpi s->d1->timeout_duration = 1; 348b09c1e06Sderaadt BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, 349b09c1e06Sderaadt &(s->d1->next_timeout)); 3500579501cSmpi /* Clear retransmission buffer */ 3510579501cSmpi dtls1_clear_record_buffer(s); 3520579501cSmpi } 3530579501cSmpi 3544a47b859Sjsing int 3554a47b859Sjsing dtls1_check_timeout_num(SSL *s) 3560579501cSmpi { 357f19d9718Sjsing s->d1->timeout.num_alerts++; 3580579501cSmpi 3590579501cSmpi /* Reduce MTU after 2 unsuccessful retransmissions */ 360f19d9718Sjsing if (s->d1->timeout.num_alerts > 2) { 361f19d9718Sjsing s->d1->mtu = BIO_ctrl(SSL_get_wbio(s), 362b09c1e06Sderaadt BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL); 3634a47b859Sjsing 3640579501cSmpi } 3650579501cSmpi 366f19d9718Sjsing if (s->d1->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT) { 3670579501cSmpi /* fail the connection, enough alerts have been sent */ 368c9d7abb7Sbeck SSLerror(s, SSL_R_READ_TIMEOUT_EXPIRED); 3690579501cSmpi return -1; 3700579501cSmpi } 3710579501cSmpi 3720579501cSmpi return 0; 3730579501cSmpi } 3740579501cSmpi 3754a47b859Sjsing int 3764a47b859Sjsing dtls1_handle_timeout(SSL *s) 3770579501cSmpi { 3780579501cSmpi /* if no timer is expired, don't do anything */ 3794a47b859Sjsing if (!dtls1_is_timer_expired(s)) { 3800579501cSmpi return 0; 3810579501cSmpi } 3820579501cSmpi 3830579501cSmpi dtls1_double_timeout(s); 3840579501cSmpi 3850579501cSmpi if (dtls1_check_timeout_num(s) < 0) 3860579501cSmpi return -1; 3870579501cSmpi 388f19d9718Sjsing s->d1->timeout.read_timeouts++; 389f19d9718Sjsing if (s->d1->timeout.read_timeouts > DTLS1_TMO_READ_COUNT) { 390f19d9718Sjsing s->d1->timeout.read_timeouts = 1; 3910579501cSmpi } 3920579501cSmpi 3930579501cSmpi dtls1_start_timer(s); 3940579501cSmpi return dtls1_retransmit_buffered_messages(s); 3950579501cSmpi } 3960579501cSmpi 3974a47b859Sjsing int 3984a47b859Sjsing dtls1_listen(SSL *s, struct sockaddr *client) 3990579501cSmpi { 4000579501cSmpi int ret; 4010579501cSmpi 4023e1f01a5Stedu /* Ensure there is no state left over from a previous invocation */ 4033e1f01a5Stedu SSL_clear(s); 4043e1f01a5Stedu 4050579501cSmpi SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE); 406f19d9718Sjsing s->d1->listen = 1; 4070579501cSmpi 4080579501cSmpi ret = SSL_accept(s); 4094a47b859Sjsing if (ret <= 0) 4104a47b859Sjsing return ret; 4110579501cSmpi 4120579501cSmpi (void)BIO_dgram_get_peer(SSL_get_rbio(s), client); 4130579501cSmpi return 1; 4140579501cSmpi } 415