xref: /openbsd/lib/libssl/d1_lib.c (revision 3e1f01a5)
1*3e1f01a5Stedu /* $OpenBSD: d1_lib.c,v 1.28 2015/03/19 14:00:22 tedu 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>
620579501cSmpi 
630579501cSmpi #include <netinet/in.h>
640579501cSmpi 
655650a0e1Sdjm #include <stdio.h>
66c5899dbcSjsing 
675650a0e1Sdjm #include <openssl/objects.h>
6846859c4aSjsing 
6946859c4aSjsing #include "pqueue.h"
705650a0e1Sdjm #include "ssl_locl.h"
715650a0e1Sdjm 
720579501cSmpi int dtls1_listen(SSL *s, struct sockaddr *client);
735650a0e1Sdjm 
745650a0e1Sdjm SSL3_ENC_METHOD DTLSv1_enc_data = {
7503e4e561Sjsing 	.enc = dtls1_enc,
7603e4e561Sjsing 	.mac = tls1_mac,
7703e4e561Sjsing 	.setup_key_block = tls1_setup_key_block,
7803e4e561Sjsing 	.generate_master_secret = tls1_generate_master_secret,
7903e4e561Sjsing 	.change_cipher_state = tls1_change_cipher_state,
8003e4e561Sjsing 	.final_finish_mac = tls1_final_finish_mac,
8103e4e561Sjsing 	.finish_mac_length = TLS1_FINISH_MAC_LENGTH,
8203e4e561Sjsing 	.cert_verify_mac = tls1_cert_verify_mac,
8303e4e561Sjsing 	.client_finished_label = TLS_MD_CLIENT_FINISH_CONST,
8403e4e561Sjsing 	.client_finished_label_len = TLS_MD_CLIENT_FINISH_CONST_SIZE,
8503e4e561Sjsing 	.server_finished_label = TLS_MD_SERVER_FINISH_CONST,
8603e4e561Sjsing 	.server_finished_label_len = TLS_MD_SERVER_FINISH_CONST_SIZE,
8703e4e561Sjsing 	.alert_value = tls1_alert_code,
8803e4e561Sjsing 	.export_keying_material = tls1_export_keying_material,
893f6fa97bSjsing 	.enc_flags = SSL_ENC_FLAG_DTLS|SSL_ENC_FLAG_EXPLICIT_IV,
905650a0e1Sdjm };
915650a0e1Sdjm 
924a47b859Sjsing long
934a47b859Sjsing dtls1_default_timeout(void)
945650a0e1Sdjm {
955650a0e1Sdjm 	/* 2 hours, the 24 hours mentioned in the DTLSv1 spec
965650a0e1Sdjm 	 * is way too long for http, the cache would over fill */
975650a0e1Sdjm 	return (60*60*2);
985650a0e1Sdjm }
995650a0e1Sdjm 
1004a47b859Sjsing int
1014a47b859Sjsing dtls1_new(SSL *s)
1025650a0e1Sdjm {
1035650a0e1Sdjm 	DTLS1_STATE *d1;
1045650a0e1Sdjm 
1054a47b859Sjsing 	if (!ssl3_new(s))
1064a47b859Sjsing 		return (0);
107b036fe71Slogan 	if ((d1 = calloc(1, sizeof *d1)) == NULL) {
108b036fe71Slogan 		ssl3_free(s);
109d870f21cSderaadt 		return (0);
110b036fe71Slogan 	}
1115650a0e1Sdjm 
1125650a0e1Sdjm 	/* d1->handshake_epoch=0; */
1135650a0e1Sdjm 
1145650a0e1Sdjm 	d1->unprocessed_rcds.q = pqueue_new();
1155650a0e1Sdjm 	d1->processed_rcds.q = pqueue_new();
1165650a0e1Sdjm 	d1->buffered_messages = pqueue_new();
1175650a0e1Sdjm 	d1->sent_messages = pqueue_new();
1180579501cSmpi 	d1->buffered_app_data.q = pqueue_new();
1195650a0e1Sdjm 
1204a47b859Sjsing 	if (s->server) {
1215650a0e1Sdjm 		d1->cookie_len = sizeof(s->d1->cookie);
1225650a0e1Sdjm 	}
1235650a0e1Sdjm 
1244a47b859Sjsing 	if (!d1->unprocessed_rcds.q || !d1->processed_rcds.q ||
1254a47b859Sjsing 	    !d1->buffered_messages || !d1->sent_messages ||
1264a47b859Sjsing 	    !d1->buffered_app_data.q) {
1274a47b859Sjsing 		if (d1->unprocessed_rcds.q)
1284a47b859Sjsing 			pqueue_free(d1->unprocessed_rcds.q);
1294a47b859Sjsing 		if (d1->processed_rcds.q)
1304a47b859Sjsing 			pqueue_free(d1->processed_rcds.q);
1314a47b859Sjsing 		if (d1->buffered_messages)
1324a47b859Sjsing 			pqueue_free(d1->buffered_messages);
1334a47b859Sjsing 		if (d1->sent_messages)
1344a47b859Sjsing 			pqueue_free(d1->sent_messages);
1354a47b859Sjsing 		if (d1->buffered_app_data.q)
1364a47b859Sjsing 			pqueue_free(d1->buffered_app_data.q);
1376f3a6cb1Sbeck 		free(d1);
138d0eebffaSmiod 		ssl3_free(s);
1395650a0e1Sdjm 		return (0);
1405650a0e1Sdjm 	}
1415650a0e1Sdjm 
1425650a0e1Sdjm 	s->d1 = d1;
1435650a0e1Sdjm 	s->method->ssl_clear(s);
1445650a0e1Sdjm 	return (1);
1455650a0e1Sdjm }
1465650a0e1Sdjm 
1474a47b859Sjsing static void
1484a47b859Sjsing dtls1_clear_queues(SSL *s)
1495650a0e1Sdjm {
1505650a0e1Sdjm 	pitem *item = NULL;
1515650a0e1Sdjm 	hm_fragment *frag = NULL;
1520579501cSmpi 	DTLS1_RECORD_DATA *rdata;
1535650a0e1Sdjm 
1544a47b859Sjsing 	while ((item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL) {
1550579501cSmpi 		rdata = (DTLS1_RECORD_DATA *) item->data;
1566f3a6cb1Sbeck 		free(rdata->rbuf.buf);
1576f3a6cb1Sbeck 		free(item->data);
1585650a0e1Sdjm 		pitem_free(item);
1595650a0e1Sdjm 	}
1605650a0e1Sdjm 
1614a47b859Sjsing 	while ((item = pqueue_pop(s->d1->processed_rcds.q)) != NULL) {
1620579501cSmpi 		rdata = (DTLS1_RECORD_DATA *) item->data;
1636f3a6cb1Sbeck 		free(rdata->rbuf.buf);
1646f3a6cb1Sbeck 		free(item->data);
1655650a0e1Sdjm 		pitem_free(item);
1665650a0e1Sdjm 	}
1675650a0e1Sdjm 
1684a47b859Sjsing 	while ((item = pqueue_pop(s->d1->buffered_messages)) != NULL) {
1695650a0e1Sdjm 		frag = (hm_fragment *)item->data;
1706f3a6cb1Sbeck 		free(frag->fragment);
1716f3a6cb1Sbeck 		free(frag);
1725650a0e1Sdjm 		pitem_free(item);
1735650a0e1Sdjm 	}
1745650a0e1Sdjm 
1754a47b859Sjsing 	while ((item = pqueue_pop(s->d1->sent_messages)) != NULL) {
1765650a0e1Sdjm 		frag = (hm_fragment *)item->data;
1776f3a6cb1Sbeck 		free(frag->fragment);
1786f3a6cb1Sbeck 		free(frag);
1795650a0e1Sdjm 		pitem_free(item);
1805650a0e1Sdjm 	}
1810579501cSmpi 
1824a47b859Sjsing 	while ((item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL) {
1833e6428bcSmiod 		rdata = (DTLS1_RECORD_DATA *) item->data;
1843e6428bcSmiod 		free(rdata->rbuf.buf);
1853e6428bcSmiod 		free(item->data);
1860579501cSmpi 		pitem_free(item);
1870579501cSmpi 	}
1880579501cSmpi }
1890579501cSmpi 
1904a47b859Sjsing void
1914a47b859Sjsing dtls1_free(SSL *s)
1920579501cSmpi {
1930579501cSmpi 	ssl3_free(s);
1940579501cSmpi 
1950579501cSmpi 	dtls1_clear_queues(s);
1960579501cSmpi 
1970579501cSmpi 	pqueue_free(s->d1->unprocessed_rcds.q);
1980579501cSmpi 	pqueue_free(s->d1->processed_rcds.q);
1990579501cSmpi 	pqueue_free(s->d1->buffered_messages);
2009a0dbe41Sdjm 	pqueue_free(s->d1->sent_messages);
2010579501cSmpi 	pqueue_free(s->d1->buffered_app_data.q);
2025650a0e1Sdjm 
203d0eebffaSmiod 	OPENSSL_cleanse(s->d1, sizeof *s->d1);
2046f3a6cb1Sbeck 	free(s->d1);
2050579501cSmpi 	s->d1 = NULL;
2065650a0e1Sdjm }
2075650a0e1Sdjm 
2084a47b859Sjsing void
2094a47b859Sjsing dtls1_clear(SSL *s)
2105650a0e1Sdjm {
2110579501cSmpi 	pqueue unprocessed_rcds;
2120579501cSmpi 	pqueue processed_rcds;
2130579501cSmpi 	pqueue buffered_messages;
2140579501cSmpi 	pqueue sent_messages;
2150579501cSmpi 	pqueue buffered_app_data;
2160579501cSmpi 	unsigned int mtu;
2170579501cSmpi 
2184a47b859Sjsing 	if (s->d1) {
2190579501cSmpi 		unprocessed_rcds = s->d1->unprocessed_rcds.q;
2200579501cSmpi 		processed_rcds = s->d1->processed_rcds.q;
2210579501cSmpi 		buffered_messages = s->d1->buffered_messages;
2220579501cSmpi 		sent_messages = s->d1->sent_messages;
2230579501cSmpi 		buffered_app_data = s->d1->buffered_app_data.q;
2240579501cSmpi 		mtu = s->d1->mtu;
2250579501cSmpi 
2260579501cSmpi 		dtls1_clear_queues(s);
2270579501cSmpi 
2280579501cSmpi 		memset(s->d1, 0, sizeof(*(s->d1)));
2290579501cSmpi 
2304a47b859Sjsing 		if (s->server) {
2310579501cSmpi 			s->d1->cookie_len = sizeof(s->d1->cookie);
2320579501cSmpi 		}
2330579501cSmpi 
2344a47b859Sjsing 		if (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU) {
2350579501cSmpi 			s->d1->mtu = mtu;
2360579501cSmpi 		}
2370579501cSmpi 
2380579501cSmpi 		s->d1->unprocessed_rcds.q = unprocessed_rcds;
2390579501cSmpi 		s->d1->processed_rcds.q = processed_rcds;
2400579501cSmpi 		s->d1->buffered_messages = buffered_messages;
2410579501cSmpi 		s->d1->sent_messages = sent_messages;
2420579501cSmpi 		s->d1->buffered_app_data.q = buffered_app_data;
2430579501cSmpi 	}
2440579501cSmpi 
2455650a0e1Sdjm 	ssl3_clear(s);
2460579501cSmpi 	if (s->options & SSL_OP_CISCO_ANYCONNECT)
2470579501cSmpi 		s->version = DTLS1_BAD_VER;
2480579501cSmpi 	else
2495650a0e1Sdjm 		s->version = DTLS1_VERSION;
2505650a0e1Sdjm }
2515650a0e1Sdjm 
2524a47b859Sjsing long
2534a47b859Sjsing dtls1_ctrl(SSL *s, int cmd, long larg, void *parg)
2540579501cSmpi {
2550579501cSmpi 	int ret = 0;
2560579501cSmpi 
2574a47b859Sjsing 	switch (cmd) {
2580579501cSmpi 	case DTLS_CTRL_GET_TIMEOUT:
2594a47b859Sjsing 		if (dtls1_get_timeout(s, (struct timeval*) parg) != NULL) {
2600579501cSmpi 			ret = 1;
2610579501cSmpi 		}
2620579501cSmpi 		break;
2630579501cSmpi 	case DTLS_CTRL_HANDLE_TIMEOUT:
2640579501cSmpi 		ret = dtls1_handle_timeout(s);
2650579501cSmpi 		break;
2660579501cSmpi 	case DTLS_CTRL_LISTEN:
2670579501cSmpi 		ret = dtls1_listen(s, parg);
2680579501cSmpi 		break;
2690579501cSmpi 
2700579501cSmpi 	default:
2710579501cSmpi 		ret = ssl3_ctrl(s, cmd, larg, parg);
2720579501cSmpi 		break;
2730579501cSmpi 	}
2740579501cSmpi 	return (ret);
2750579501cSmpi }
2760579501cSmpi 
2775650a0e1Sdjm /*
2785650a0e1Sdjm  * As it's impossible to use stream ciphers in "datagram" mode, this
2795650a0e1Sdjm  * simple filter is designed to disengage them in DTLS. Unfortunately
2805650a0e1Sdjm  * there is no universal way to identify stream SSL_CIPHER, so we have
2815650a0e1Sdjm  * to explicitly list their SSL_* codes. Currently RC4 is the only one
2825650a0e1Sdjm  * available, but if new ones emerge, they will have to be added...
2835650a0e1Sdjm  */
284dbea66cdSguenther const SSL_CIPHER *
285dbea66cdSguenther dtls1_get_cipher(unsigned int u)
2865650a0e1Sdjm {
2870579501cSmpi 	const SSL_CIPHER *ciph = ssl3_get_cipher(u);
2885650a0e1Sdjm 
2894a47b859Sjsing 	if (ciph != NULL) {
2900579501cSmpi 		if (ciph->algorithm_enc == SSL_RC4)
2915650a0e1Sdjm 			return NULL;
2925650a0e1Sdjm 	}
2935650a0e1Sdjm 
2945650a0e1Sdjm 	return ciph;
2955650a0e1Sdjm }
2960579501cSmpi 
2974a47b859Sjsing void
2984a47b859Sjsing dtls1_start_timer(SSL *s)
2990579501cSmpi {
3000579501cSmpi 
3010579501cSmpi 	/* If timer is not set, initialize duration with 1 second */
3024a47b859Sjsing 	if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) {
3030579501cSmpi 		s->d1->timeout_duration = 1;
3040579501cSmpi 	}
3050579501cSmpi 
3060579501cSmpi 	/* Set timeout to current time */
30733e311cfSderaadt 	gettimeofday(&(s->d1->next_timeout), NULL);
3080579501cSmpi 
3090579501cSmpi 	/* Add duration to current time */
3100579501cSmpi 	s->d1->next_timeout.tv_sec += s->d1->timeout_duration;
311b09c1e06Sderaadt 	BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
312b09c1e06Sderaadt 	    &(s->d1->next_timeout));
3130579501cSmpi }
3140579501cSmpi 
3154a47b859Sjsing struct timeval*
316b09c1e06Sderaadt dtls1_get_timeout(SSL *s, struct timeval* timeleft)
317b09c1e06Sderaadt {
3180579501cSmpi 	struct timeval timenow;
3190579501cSmpi 
3200579501cSmpi 	/* If no timeout is set, just return NULL */
3214a47b859Sjsing 	if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) {
3220579501cSmpi 		return NULL;
3230579501cSmpi 	}
3240579501cSmpi 
3250579501cSmpi 	/* Get current time */
32633e311cfSderaadt 	gettimeofday(&timenow, NULL);
3270579501cSmpi 
3280579501cSmpi 	/* If timer already expired, set remaining time to 0 */
3290579501cSmpi 	if (s->d1->next_timeout.tv_sec < timenow.tv_sec ||
3300579501cSmpi 	    (s->d1->next_timeout.tv_sec == timenow.tv_sec &&
3314a47b859Sjsing 	     s->d1->next_timeout.tv_usec <= timenow.tv_usec)) {
3320579501cSmpi 		memset(timeleft, 0, sizeof(struct timeval));
3330579501cSmpi 		return timeleft;
3340579501cSmpi 	}
3350579501cSmpi 
3360579501cSmpi 	/* Calculate time left until timer expires */
3370579501cSmpi 	memcpy(timeleft, &(s->d1->next_timeout), sizeof(struct timeval));
3380579501cSmpi 	timeleft->tv_sec -= timenow.tv_sec;
3390579501cSmpi 	timeleft->tv_usec -= timenow.tv_usec;
3404a47b859Sjsing 	if (timeleft->tv_usec < 0) {
3410579501cSmpi 		timeleft->tv_sec--;
3420579501cSmpi 		timeleft->tv_usec += 1000000;
3430579501cSmpi 	}
3440579501cSmpi 
3450579501cSmpi 	/* If remaining time is less than 15 ms, set it to 0
3460579501cSmpi 	 * to prevent issues because of small devergences with
3470579501cSmpi 	 * socket timeouts.
3480579501cSmpi 	 */
3494a47b859Sjsing 	if (timeleft->tv_sec == 0 && timeleft->tv_usec < 15000) {
3500579501cSmpi 		memset(timeleft, 0, sizeof(struct timeval));
3510579501cSmpi 	}
3520579501cSmpi 
3530579501cSmpi 
3540579501cSmpi 	return timeleft;
3550579501cSmpi }
3560579501cSmpi 
3574a47b859Sjsing int
3584a47b859Sjsing dtls1_is_timer_expired(SSL *s)
3590579501cSmpi {
3600579501cSmpi 	struct timeval timeleft;
3610579501cSmpi 
3620579501cSmpi 	/* Get time left until timeout, return false if no timer running */
3634a47b859Sjsing 	if (dtls1_get_timeout(s, &timeleft) == NULL) {
3640579501cSmpi 		return 0;
3650579501cSmpi 	}
3660579501cSmpi 
3670579501cSmpi 	/* Return false if timer is not expired yet */
3684a47b859Sjsing 	if (timeleft.tv_sec > 0 || timeleft.tv_usec > 0) {
3690579501cSmpi 		return 0;
3700579501cSmpi 	}
3710579501cSmpi 
3720579501cSmpi 	/* Timer expired, so return true */
3730579501cSmpi 	return 1;
3740579501cSmpi }
3750579501cSmpi 
3764a47b859Sjsing void
3774a47b859Sjsing dtls1_double_timeout(SSL *s)
3780579501cSmpi {
3790579501cSmpi 	s->d1->timeout_duration *= 2;
3800579501cSmpi 	if (s->d1->timeout_duration > 60)
3810579501cSmpi 		s->d1->timeout_duration = 60;
3820579501cSmpi 	dtls1_start_timer(s);
3830579501cSmpi }
3840579501cSmpi 
3854a47b859Sjsing void
3864a47b859Sjsing dtls1_stop_timer(SSL *s)
3870579501cSmpi {
3880579501cSmpi 	/* Reset everything */
3890579501cSmpi 	memset(&(s->d1->timeout), 0, sizeof(struct dtls1_timeout_st));
3900579501cSmpi 	memset(&(s->d1->next_timeout), 0, sizeof(struct timeval));
3910579501cSmpi 	s->d1->timeout_duration = 1;
392b09c1e06Sderaadt 	BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
393b09c1e06Sderaadt 	    &(s->d1->next_timeout));
3940579501cSmpi 	/* Clear retransmission buffer */
3950579501cSmpi 	dtls1_clear_record_buffer(s);
3960579501cSmpi }
3970579501cSmpi 
3984a47b859Sjsing int
3994a47b859Sjsing dtls1_check_timeout_num(SSL *s)
4000579501cSmpi {
4010579501cSmpi 	s->d1->timeout.num_alerts++;
4020579501cSmpi 
4030579501cSmpi 	/* Reduce MTU after 2 unsuccessful retransmissions */
4044a47b859Sjsing 	if (s->d1->timeout.num_alerts > 2) {
405b09c1e06Sderaadt 		s->d1->mtu = BIO_ctrl(SSL_get_wbio(s),
406b09c1e06Sderaadt 		    BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL);
4074a47b859Sjsing 
4080579501cSmpi 	}
4090579501cSmpi 
4104a47b859Sjsing 	if (s->d1->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT) {
4110579501cSmpi 		/* fail the connection, enough alerts have been sent */
4120579501cSmpi 		SSLerr(SSL_F_DTLS1_CHECK_TIMEOUT_NUM, SSL_R_READ_TIMEOUT_EXPIRED);
4130579501cSmpi 		return -1;
4140579501cSmpi 	}
4150579501cSmpi 
4160579501cSmpi 	return 0;
4170579501cSmpi }
4180579501cSmpi 
4194a47b859Sjsing int
4204a47b859Sjsing dtls1_handle_timeout(SSL *s)
4210579501cSmpi {
4220579501cSmpi 	/* if no timer is expired, don't do anything */
4234a47b859Sjsing 	if (!dtls1_is_timer_expired(s)) {
4240579501cSmpi 		return 0;
4250579501cSmpi 	}
4260579501cSmpi 
4270579501cSmpi 	dtls1_double_timeout(s);
4280579501cSmpi 
4290579501cSmpi 	if (dtls1_check_timeout_num(s) < 0)
4300579501cSmpi 		return -1;
4310579501cSmpi 
4320579501cSmpi 	s->d1->timeout.read_timeouts++;
4334a47b859Sjsing 	if (s->d1->timeout.read_timeouts > DTLS1_TMO_READ_COUNT) {
4340579501cSmpi 		s->d1->timeout.read_timeouts = 1;
4350579501cSmpi 	}
4360579501cSmpi 
4370579501cSmpi 	dtls1_start_timer(s);
4380579501cSmpi 	return dtls1_retransmit_buffered_messages(s);
4390579501cSmpi }
4400579501cSmpi 
4414a47b859Sjsing int
4424a47b859Sjsing dtls1_listen(SSL *s, struct sockaddr *client)
4430579501cSmpi {
4440579501cSmpi 	int ret;
4450579501cSmpi 
446*3e1f01a5Stedu 	/* Ensure there is no state left over from a previous invocation */
447*3e1f01a5Stedu 	SSL_clear(s);
448*3e1f01a5Stedu 
4490579501cSmpi 	SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE);
4500579501cSmpi 	s->d1->listen = 1;
4510579501cSmpi 
4520579501cSmpi 	ret = SSL_accept(s);
4534a47b859Sjsing 	if (ret <= 0)
4544a47b859Sjsing 		return ret;
4550579501cSmpi 
4560579501cSmpi 	(void)BIO_dgram_get_peer(SSL_get_rbio(s), client);
4570579501cSmpi 	return 1;
4580579501cSmpi }
45963152afbSjsing 
46063152afbSjsing void
46163152afbSjsing dtls1_build_sequence_number(unsigned char *dst, unsigned char *seq,
46263152afbSjsing     unsigned short epoch)
46363152afbSjsing {
46463152afbSjsing 	unsigned char dtlsseq[SSL3_SEQUENCE_SIZE];
46563152afbSjsing 	unsigned char *p;
46663152afbSjsing 
46763152afbSjsing 	p = dtlsseq;
46863152afbSjsing 	s2n(epoch, p);
46963152afbSjsing 	memcpy(p, &seq[2], SSL3_SEQUENCE_SIZE - 2);
47063152afbSjsing 	memcpy(dst, dtlsseq, SSL3_SEQUENCE_SIZE);
47163152afbSjsing }
472