1*c9675a23Stb /* $OpenBSD: d1_lib.c,v 1.64 2022/11/26 16:08:55 tb 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
70*c9675a23Stb #include "dtls_local.h"
7146859c4aSjsing #include "pqueue.h"
72*c9675a23Stb #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
dtls1_new(SSL * s)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
dtls1_drain_rcontents(pqueue queue)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
dtls1_drain_records(pqueue queue)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
dtls1_drain_fragments(pqueue queue)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
dtls1_clear_queues(SSL * s)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
dtls1_free(SSL * s)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
dtls1_clear(SSL * s)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
dtls1_ctrl(SSL * s,int cmd,long larg,void * parg)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
2535650a0e1Sdjm /*
2545650a0e1Sdjm * As it's impossible to use stream ciphers in "datagram" mode, this
2555650a0e1Sdjm * simple filter is designed to disengage them in DTLS. Unfortunately
2565650a0e1Sdjm * there is no universal way to identify stream SSL_CIPHER, so we have
2575650a0e1Sdjm * to explicitly list their SSL_* codes. Currently RC4 is the only one
2585650a0e1Sdjm * available, but if new ones emerge, they will have to be added...
2595650a0e1Sdjm */
260dbea66cdSguenther const SSL_CIPHER *
dtls1_get_cipher(unsigned int u)261dbea66cdSguenther dtls1_get_cipher(unsigned int u)
2625650a0e1Sdjm {
26335328106Sjsing const SSL_CIPHER *cipher;
2645650a0e1Sdjm
26535328106Sjsing if ((cipher = ssl3_get_cipher(u)) == NULL)
2665650a0e1Sdjm return NULL;
2675650a0e1Sdjm
26835328106Sjsing if (cipher->algorithm_enc == SSL_RC4)
26935328106Sjsing return NULL;
27035328106Sjsing
27135328106Sjsing return cipher;
2725650a0e1Sdjm }
2730579501cSmpi
2744a47b859Sjsing void
dtls1_start_timer(SSL * s)2754a47b859Sjsing dtls1_start_timer(SSL *s)
2760579501cSmpi {
2770579501cSmpi
2780579501cSmpi /* If timer is not set, initialize duration with 1 second */
2794a47b859Sjsing if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) {
2800579501cSmpi s->d1->timeout_duration = 1;
2810579501cSmpi }
2820579501cSmpi
2830579501cSmpi /* Set timeout to current time */
28433e311cfSderaadt gettimeofday(&(s->d1->next_timeout), NULL);
2850579501cSmpi
2860579501cSmpi /* Add duration to current time */
2870579501cSmpi s->d1->next_timeout.tv_sec += s->d1->timeout_duration;
288b09c1e06Sderaadt BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
289f7271532Sbeck &s->d1->next_timeout);
2900579501cSmpi }
2910579501cSmpi
2924a47b859Sjsing struct timeval*
dtls1_get_timeout(SSL * s,struct timeval * timeleft)293b09c1e06Sderaadt dtls1_get_timeout(SSL *s, struct timeval* timeleft)
294b09c1e06Sderaadt {
2950579501cSmpi struct timeval timenow;
2960579501cSmpi
2970579501cSmpi /* If no timeout is set, just return NULL */
2984a47b859Sjsing if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) {
2990579501cSmpi return NULL;
3000579501cSmpi }
3010579501cSmpi
3020579501cSmpi /* Get current time */
30333e311cfSderaadt gettimeofday(&timenow, NULL);
3040579501cSmpi
3050579501cSmpi /* If timer already expired, set remaining time to 0 */
3060579501cSmpi if (s->d1->next_timeout.tv_sec < timenow.tv_sec ||
3070579501cSmpi (s->d1->next_timeout.tv_sec == timenow.tv_sec &&
3084a47b859Sjsing s->d1->next_timeout.tv_usec <= timenow.tv_usec)) {
3090579501cSmpi memset(timeleft, 0, sizeof(struct timeval));
3100579501cSmpi return timeleft;
3110579501cSmpi }
3120579501cSmpi
3130579501cSmpi /* Calculate time left until timer expires */
3140579501cSmpi memcpy(timeleft, &(s->d1->next_timeout), sizeof(struct timeval));
3150579501cSmpi timeleft->tv_sec -= timenow.tv_sec;
3160579501cSmpi timeleft->tv_usec -= timenow.tv_usec;
3174a47b859Sjsing if (timeleft->tv_usec < 0) {
3180579501cSmpi timeleft->tv_sec--;
3190579501cSmpi timeleft->tv_usec += 1000000;
3200579501cSmpi }
3210579501cSmpi
3220579501cSmpi /* If remaining time is less than 15 ms, set it to 0
3230579501cSmpi * to prevent issues because of small devergences with
3240579501cSmpi * socket timeouts.
3250579501cSmpi */
3264a47b859Sjsing if (timeleft->tv_sec == 0 && timeleft->tv_usec < 15000) {
3270579501cSmpi memset(timeleft, 0, sizeof(struct timeval));
3280579501cSmpi }
3290579501cSmpi
3300579501cSmpi
3310579501cSmpi return timeleft;
3320579501cSmpi }
3330579501cSmpi
3344a47b859Sjsing int
dtls1_is_timer_expired(SSL * s)3354a47b859Sjsing dtls1_is_timer_expired(SSL *s)
3360579501cSmpi {
3370579501cSmpi struct timeval timeleft;
3380579501cSmpi
3390579501cSmpi /* Get time left until timeout, return false if no timer running */
3404a47b859Sjsing if (dtls1_get_timeout(s, &timeleft) == NULL) {
3410579501cSmpi return 0;
3420579501cSmpi }
3430579501cSmpi
3440579501cSmpi /* Return false if timer is not expired yet */
3454a47b859Sjsing if (timeleft.tv_sec > 0 || timeleft.tv_usec > 0) {
3460579501cSmpi return 0;
3470579501cSmpi }
3480579501cSmpi
3490579501cSmpi /* Timer expired, so return true */
3500579501cSmpi return 1;
3510579501cSmpi }
3520579501cSmpi
3534a47b859Sjsing void
dtls1_double_timeout(SSL * s)3544a47b859Sjsing dtls1_double_timeout(SSL *s)
3550579501cSmpi {
3560579501cSmpi s->d1->timeout_duration *= 2;
3570579501cSmpi if (s->d1->timeout_duration > 60)
3580579501cSmpi s->d1->timeout_duration = 60;
3590579501cSmpi dtls1_start_timer(s);
3600579501cSmpi }
3610579501cSmpi
3624a47b859Sjsing void
dtls1_stop_timer(SSL * s)3634a47b859Sjsing dtls1_stop_timer(SSL *s)
3640579501cSmpi {
3650579501cSmpi /* Reset everything */
366f19d9718Sjsing memset(&(s->d1->timeout), 0, sizeof(struct dtls1_timeout_st));
3670579501cSmpi memset(&(s->d1->next_timeout), 0, sizeof(struct timeval));
3680579501cSmpi s->d1->timeout_duration = 1;
369b09c1e06Sderaadt BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
370b09c1e06Sderaadt &(s->d1->next_timeout));
3710579501cSmpi /* Clear retransmission buffer */
3720579501cSmpi dtls1_clear_record_buffer(s);
3730579501cSmpi }
3740579501cSmpi
3754a47b859Sjsing int
dtls1_check_timeout_num(SSL * s)3764a47b859Sjsing dtls1_check_timeout_num(SSL *s)
3770579501cSmpi {
378f19d9718Sjsing s->d1->timeout.num_alerts++;
3790579501cSmpi
3800579501cSmpi /* Reduce MTU after 2 unsuccessful retransmissions */
381f19d9718Sjsing if (s->d1->timeout.num_alerts > 2) {
382f19d9718Sjsing s->d1->mtu = BIO_ctrl(SSL_get_wbio(s),
383b09c1e06Sderaadt BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL);
3844a47b859Sjsing
3850579501cSmpi }
3860579501cSmpi
387f19d9718Sjsing if (s->d1->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT) {
3880579501cSmpi /* fail the connection, enough alerts have been sent */
389c9d7abb7Sbeck SSLerror(s, SSL_R_READ_TIMEOUT_EXPIRED);
3900579501cSmpi return -1;
3910579501cSmpi }
3920579501cSmpi
3930579501cSmpi return 0;
3940579501cSmpi }
3950579501cSmpi
3964a47b859Sjsing int
dtls1_handle_timeout(SSL * s)3974a47b859Sjsing dtls1_handle_timeout(SSL *s)
3980579501cSmpi {
3990579501cSmpi /* if no timer is expired, don't do anything */
4004a47b859Sjsing if (!dtls1_is_timer_expired(s)) {
4010579501cSmpi return 0;
4020579501cSmpi }
4030579501cSmpi
4040579501cSmpi dtls1_double_timeout(s);
4050579501cSmpi
4060579501cSmpi if (dtls1_check_timeout_num(s) < 0)
4070579501cSmpi return -1;
4080579501cSmpi
409f19d9718Sjsing s->d1->timeout.read_timeouts++;
410f19d9718Sjsing if (s->d1->timeout.read_timeouts > DTLS1_TMO_READ_COUNT) {
411f19d9718Sjsing s->d1->timeout.read_timeouts = 1;
4120579501cSmpi }
4130579501cSmpi
4140579501cSmpi dtls1_start_timer(s);
4150579501cSmpi return dtls1_retransmit_buffered_messages(s);
4160579501cSmpi }
4170579501cSmpi
4184a47b859Sjsing int
dtls1_listen(SSL * s,struct sockaddr * client)4194a47b859Sjsing dtls1_listen(SSL *s, struct sockaddr *client)
4200579501cSmpi {
4210579501cSmpi int ret;
4220579501cSmpi
4233e1f01a5Stedu /* Ensure there is no state left over from a previous invocation */
4243e1f01a5Stedu SSL_clear(s);
4253e1f01a5Stedu
4260579501cSmpi SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE);
427f19d9718Sjsing s->d1->listen = 1;
4280579501cSmpi
4290579501cSmpi ret = SSL_accept(s);
4304a47b859Sjsing if (ret <= 0)
4314a47b859Sjsing return ret;
4320579501cSmpi
4330579501cSmpi (void)BIO_dgram_get_peer(SSL_get_rbio(s), client);
4340579501cSmpi return 1;
4350579501cSmpi }
436