xref: /dflybsd-src/crypto/libressl/ssl/d1_lib.c (revision 961e30ea7dc61d1112b778ea4981eac68129fb86)
1*de0e0e4dSAntonio Huete Jimenez /* $OpenBSD: d1_lib.c,v 1.61 2021/10/23 13:36:03 jsing Exp $ */
2f5b1c8a1SJohn Marino /*
3f5b1c8a1SJohn Marino  * DTLS implementation written by Nagendra Modadugu
4f5b1c8a1SJohn Marino  * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
5f5b1c8a1SJohn Marino  */
6f5b1c8a1SJohn Marino /* ====================================================================
7f5b1c8a1SJohn Marino  * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
8f5b1c8a1SJohn Marino  *
9f5b1c8a1SJohn Marino  * Redistribution and use in source and binary forms, with or without
10f5b1c8a1SJohn Marino  * modification, are permitted provided that the following conditions
11f5b1c8a1SJohn Marino  * are met:
12f5b1c8a1SJohn Marino  *
13f5b1c8a1SJohn Marino  * 1. Redistributions of source code must retain the above copyright
14f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer.
15f5b1c8a1SJohn Marino  *
16f5b1c8a1SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
17f5b1c8a1SJohn Marino  *    notice, this list of conditions and the following disclaimer in
18f5b1c8a1SJohn Marino  *    the documentation and/or other materials provided with the
19f5b1c8a1SJohn Marino  *    distribution.
20f5b1c8a1SJohn Marino  *
21f5b1c8a1SJohn Marino  * 3. All advertising materials mentioning features or use of this
22f5b1c8a1SJohn Marino  *    software must display the following acknowledgment:
23f5b1c8a1SJohn Marino  *    "This product includes software developed by the OpenSSL Project
24f5b1c8a1SJohn Marino  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25f5b1c8a1SJohn Marino  *
26f5b1c8a1SJohn Marino  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27f5b1c8a1SJohn Marino  *    endorse or promote products derived from this software without
28f5b1c8a1SJohn Marino  *    prior written permission. For written permission, please contact
29f5b1c8a1SJohn Marino  *    openssl-core@OpenSSL.org.
30f5b1c8a1SJohn Marino  *
31f5b1c8a1SJohn Marino  * 5. Products derived from this software may not be called "OpenSSL"
32f5b1c8a1SJohn Marino  *    nor may "OpenSSL" appear in their names without prior written
33f5b1c8a1SJohn Marino  *    permission of the OpenSSL Project.
34f5b1c8a1SJohn Marino  *
35f5b1c8a1SJohn Marino  * 6. Redistributions of any form whatsoever must retain the following
36f5b1c8a1SJohn Marino  *    acknowledgment:
37f5b1c8a1SJohn Marino  *    "This product includes software developed by the OpenSSL Project
38f5b1c8a1SJohn Marino  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39f5b1c8a1SJohn Marino  *
40f5b1c8a1SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41f5b1c8a1SJohn Marino  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42f5b1c8a1SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43f5b1c8a1SJohn Marino  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44f5b1c8a1SJohn Marino  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45f5b1c8a1SJohn Marino  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46f5b1c8a1SJohn Marino  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47f5b1c8a1SJohn Marino  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48f5b1c8a1SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49f5b1c8a1SJohn Marino  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50f5b1c8a1SJohn Marino  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51f5b1c8a1SJohn Marino  * OF THE POSSIBILITY OF SUCH DAMAGE.
52f5b1c8a1SJohn Marino  * ====================================================================
53f5b1c8a1SJohn Marino  *
54f5b1c8a1SJohn Marino  * This product includes cryptographic software written by Eric Young
55f5b1c8a1SJohn Marino  * (eay@cryptsoft.com).  This product includes software written by Tim
56f5b1c8a1SJohn Marino  * Hudson (tjh@cryptsoft.com).
57f5b1c8a1SJohn Marino  *
58f5b1c8a1SJohn Marino  */
59f5b1c8a1SJohn Marino 
60f5b1c8a1SJohn Marino #include <sys/types.h>
61f5b1c8a1SJohn Marino #include <sys/socket.h>
62f5b1c8a1SJohn Marino #include <sys/time.h>
63f5b1c8a1SJohn Marino 
64f5b1c8a1SJohn Marino #include <netinet/in.h>
65f5b1c8a1SJohn Marino 
66f5b1c8a1SJohn Marino #include <stdio.h>
67f5b1c8a1SJohn Marino 
68f5b1c8a1SJohn Marino #include <openssl/objects.h>
69f5b1c8a1SJohn Marino 
70*de0e0e4dSAntonio Huete Jimenez #include "dtls_locl.h"
71f5b1c8a1SJohn Marino #include "pqueue.h"
72f5b1c8a1SJohn Marino #include "ssl_locl.h"
73f5b1c8a1SJohn Marino 
748edacedfSDaniel Fojt void dtls1_hm_fragment_free(hm_fragment *frag);
758edacedfSDaniel Fojt 
7672c33676SMaxim Ag static int dtls1_listen(SSL *s, struct sockaddr *client);
77f5b1c8a1SJohn Marino 
78f5b1c8a1SJohn Marino int
dtls1_new(SSL * s)79f5b1c8a1SJohn Marino dtls1_new(SSL *s)
80f5b1c8a1SJohn Marino {
81f5b1c8a1SJohn Marino 	if (!ssl3_new(s))
828edacedfSDaniel Fojt 		goto err;
83f5b1c8a1SJohn Marino 
848edacedfSDaniel Fojt 	if ((s->d1 = calloc(1, sizeof(*s->d1))) == NULL)
858edacedfSDaniel Fojt 		goto err;
86f5b1c8a1SJohn Marino 
87*de0e0e4dSAntonio Huete Jimenez 	if ((s->d1->unprocessed_rcds.q = pqueue_new()) == NULL)
888edacedfSDaniel Fojt 		goto err;
89*de0e0e4dSAntonio Huete Jimenez 	if ((s->d1->buffered_messages = pqueue_new()) == NULL)
908edacedfSDaniel Fojt 		goto err;
918edacedfSDaniel Fojt 	if ((s->d1->sent_messages = pqueue_new()) == NULL)
928edacedfSDaniel Fojt 		goto err;
93*de0e0e4dSAntonio Huete Jimenez 	if ((s->d1->buffered_app_data.q = pqueue_new()) == NULL)
948edacedfSDaniel Fojt 		goto err;
95f5b1c8a1SJohn Marino 
968edacedfSDaniel Fojt 	if (s->server)
97*de0e0e4dSAntonio Huete Jimenez 		s->d1->cookie_len = sizeof(s->d1->cookie);
98f5b1c8a1SJohn Marino 
99*de0e0e4dSAntonio Huete Jimenez 	s->method->ssl_clear(s);
100f5b1c8a1SJohn Marino 	return (1);
1018edacedfSDaniel Fojt 
1028edacedfSDaniel Fojt  err:
1038edacedfSDaniel Fojt 	dtls1_free(s);
1048edacedfSDaniel Fojt 	return (0);
1058edacedfSDaniel Fojt }
1068edacedfSDaniel Fojt 
1078edacedfSDaniel Fojt static void
dtls1_drain_records(pqueue queue)1088edacedfSDaniel Fojt dtls1_drain_records(pqueue queue)
1098edacedfSDaniel Fojt {
1108edacedfSDaniel Fojt 	pitem *item;
1118edacedfSDaniel Fojt 	DTLS1_RECORD_DATA_INTERNAL *rdata;
1128edacedfSDaniel Fojt 
1138edacedfSDaniel Fojt 	if (queue == NULL)
1148edacedfSDaniel Fojt 		return;
1158edacedfSDaniel Fojt 
1168edacedfSDaniel Fojt 	while ((item = pqueue_pop(queue)) != NULL) {
1178edacedfSDaniel Fojt 		rdata = (DTLS1_RECORD_DATA_INTERNAL *)item->data;
1188edacedfSDaniel Fojt 		ssl3_release_buffer(&rdata->rbuf);
1198edacedfSDaniel Fojt 		free(item->data);
1208edacedfSDaniel Fojt 		pitem_free(item);
1218edacedfSDaniel Fojt 	}
1228edacedfSDaniel Fojt }
1238edacedfSDaniel Fojt 
1248edacedfSDaniel Fojt static void
dtls1_drain_fragments(pqueue queue)1258edacedfSDaniel Fojt dtls1_drain_fragments(pqueue queue)
1268edacedfSDaniel Fojt {
1278edacedfSDaniel Fojt 	pitem *item;
1288edacedfSDaniel Fojt 
1298edacedfSDaniel Fojt 	if (queue == NULL)
1308edacedfSDaniel Fojt 		return;
1318edacedfSDaniel Fojt 
1328edacedfSDaniel Fojt 	while ((item = pqueue_pop(queue)) != NULL) {
1338edacedfSDaniel Fojt 		dtls1_hm_fragment_free(item->data);
1348edacedfSDaniel Fojt 		pitem_free(item);
1358edacedfSDaniel Fojt 	}
136f5b1c8a1SJohn Marino }
137f5b1c8a1SJohn Marino 
138f5b1c8a1SJohn Marino static void
dtls1_clear_queues(SSL * s)139f5b1c8a1SJohn Marino dtls1_clear_queues(SSL *s)
140f5b1c8a1SJohn Marino {
141*de0e0e4dSAntonio Huete Jimenez 	dtls1_drain_records(s->d1->unprocessed_rcds.q);
142*de0e0e4dSAntonio Huete Jimenez 	dtls1_drain_fragments(s->d1->buffered_messages);
1438edacedfSDaniel Fojt 	dtls1_drain_fragments(s->d1->sent_messages);
144*de0e0e4dSAntonio Huete Jimenez 	dtls1_drain_records(s->d1->buffered_app_data.q);
145f5b1c8a1SJohn Marino }
146f5b1c8a1SJohn Marino 
147f5b1c8a1SJohn Marino void
dtls1_free(SSL * s)148f5b1c8a1SJohn Marino dtls1_free(SSL *s)
149f5b1c8a1SJohn Marino {
150f5b1c8a1SJohn Marino 	if (s == NULL)
151f5b1c8a1SJohn Marino 		return;
152f5b1c8a1SJohn Marino 
153f5b1c8a1SJohn Marino 	ssl3_free(s);
154f5b1c8a1SJohn Marino 
155*de0e0e4dSAntonio Huete Jimenez 	if (s->d1 == NULL)
156*de0e0e4dSAntonio Huete Jimenez 		return;
157*de0e0e4dSAntonio Huete Jimenez 
158f5b1c8a1SJohn Marino 	dtls1_clear_queues(s);
159f5b1c8a1SJohn Marino 
160*de0e0e4dSAntonio Huete Jimenez 	pqueue_free(s->d1->unprocessed_rcds.q);
161*de0e0e4dSAntonio Huete Jimenez 	pqueue_free(s->d1->buffered_messages);
162f5b1c8a1SJohn Marino 	pqueue_free(s->d1->sent_messages);
163*de0e0e4dSAntonio Huete Jimenez 	pqueue_free(s->d1->buffered_app_data.q);
164f5b1c8a1SJohn Marino 
16572c33676SMaxim Ag 	freezero(s->d1, sizeof(*s->d1));
166f5b1c8a1SJohn Marino 	s->d1 = NULL;
167f5b1c8a1SJohn Marino }
168f5b1c8a1SJohn Marino 
169f5b1c8a1SJohn Marino void
dtls1_clear(SSL * s)170f5b1c8a1SJohn Marino dtls1_clear(SSL *s)
171f5b1c8a1SJohn Marino {
172f5b1c8a1SJohn Marino 	pqueue unprocessed_rcds;
173f5b1c8a1SJohn Marino 	pqueue buffered_messages;
174f5b1c8a1SJohn Marino 	pqueue sent_messages;
175f5b1c8a1SJohn Marino 	pqueue buffered_app_data;
176f5b1c8a1SJohn Marino 	unsigned int mtu;
177f5b1c8a1SJohn Marino 
178f5b1c8a1SJohn Marino 	if (s->d1) {
179*de0e0e4dSAntonio Huete Jimenez 		unprocessed_rcds = s->d1->unprocessed_rcds.q;
180*de0e0e4dSAntonio Huete Jimenez 		buffered_messages = s->d1->buffered_messages;
181f5b1c8a1SJohn Marino 		sent_messages = s->d1->sent_messages;
182*de0e0e4dSAntonio Huete Jimenez 		buffered_app_data = s->d1->buffered_app_data.q;
183*de0e0e4dSAntonio Huete Jimenez 		mtu = s->d1->mtu;
184f5b1c8a1SJohn Marino 
185f5b1c8a1SJohn Marino 		dtls1_clear_queues(s);
186f5b1c8a1SJohn Marino 
18772c33676SMaxim Ag 		memset(s->d1, 0, sizeof(*s->d1));
188*de0e0e4dSAntonio Huete Jimenez 
189*de0e0e4dSAntonio Huete Jimenez 		s->d1->unprocessed_rcds.epoch =
190*de0e0e4dSAntonio Huete Jimenez 		    tls12_record_layer_read_epoch(s->internal->rl) + 1;
191f5b1c8a1SJohn Marino 
192f5b1c8a1SJohn Marino 		if (s->server) {
193*de0e0e4dSAntonio Huete Jimenez 			s->d1->cookie_len = sizeof(s->d1->cookie);
194f5b1c8a1SJohn Marino 		}
195f5b1c8a1SJohn Marino 
196f5b1c8a1SJohn Marino 		if (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU) {
197*de0e0e4dSAntonio Huete Jimenez 			s->d1->mtu = mtu;
198f5b1c8a1SJohn Marino 		}
199f5b1c8a1SJohn Marino 
200*de0e0e4dSAntonio Huete Jimenez 		s->d1->unprocessed_rcds.q = unprocessed_rcds;
201*de0e0e4dSAntonio Huete Jimenez 		s->d1->buffered_messages = buffered_messages;
202f5b1c8a1SJohn Marino 		s->d1->sent_messages = sent_messages;
203*de0e0e4dSAntonio Huete Jimenez 		s->d1->buffered_app_data.q = buffered_app_data;
204f5b1c8a1SJohn Marino 	}
205f5b1c8a1SJohn Marino 
206f5b1c8a1SJohn Marino 	ssl3_clear(s);
207f5b1c8a1SJohn Marino 
208f5b1c8a1SJohn Marino 	s->version = DTLS1_VERSION;
209f5b1c8a1SJohn Marino }
210f5b1c8a1SJohn Marino 
211f5b1c8a1SJohn Marino long
dtls1_ctrl(SSL * s,int cmd,long larg,void * parg)212f5b1c8a1SJohn Marino dtls1_ctrl(SSL *s, int cmd, long larg, void *parg)
213f5b1c8a1SJohn Marino {
214f5b1c8a1SJohn Marino 	int ret = 0;
215f5b1c8a1SJohn Marino 
216f5b1c8a1SJohn Marino 	switch (cmd) {
217f5b1c8a1SJohn Marino 	case DTLS_CTRL_GET_TIMEOUT:
218f5b1c8a1SJohn Marino 		if (dtls1_get_timeout(s, (struct timeval*) parg) != NULL) {
219f5b1c8a1SJohn Marino 			ret = 1;
220f5b1c8a1SJohn Marino 		}
221f5b1c8a1SJohn Marino 		break;
222f5b1c8a1SJohn Marino 	case DTLS_CTRL_HANDLE_TIMEOUT:
223f5b1c8a1SJohn Marino 		ret = dtls1_handle_timeout(s);
224f5b1c8a1SJohn Marino 		break;
225f5b1c8a1SJohn Marino 	case DTLS_CTRL_LISTEN:
226f5b1c8a1SJohn Marino 		ret = dtls1_listen(s, parg);
227f5b1c8a1SJohn Marino 		break;
228f5b1c8a1SJohn Marino 
229f5b1c8a1SJohn Marino 	default:
230f5b1c8a1SJohn Marino 		ret = ssl3_ctrl(s, cmd, larg, parg);
231f5b1c8a1SJohn Marino 		break;
232f5b1c8a1SJohn Marino 	}
233f5b1c8a1SJohn Marino 	return (ret);
234f5b1c8a1SJohn Marino }
235f5b1c8a1SJohn Marino 
236f5b1c8a1SJohn Marino /*
237f5b1c8a1SJohn Marino  * As it's impossible to use stream ciphers in "datagram" mode, this
238f5b1c8a1SJohn Marino  * simple filter is designed to disengage them in DTLS. Unfortunately
239f5b1c8a1SJohn Marino  * there is no universal way to identify stream SSL_CIPHER, so we have
240f5b1c8a1SJohn Marino  * to explicitly list their SSL_* codes. Currently RC4 is the only one
241f5b1c8a1SJohn Marino  * available, but if new ones emerge, they will have to be added...
242f5b1c8a1SJohn Marino  */
243f5b1c8a1SJohn Marino const SSL_CIPHER *
dtls1_get_cipher(unsigned int u)244f5b1c8a1SJohn Marino dtls1_get_cipher(unsigned int u)
245f5b1c8a1SJohn Marino {
246*de0e0e4dSAntonio Huete Jimenez 	const SSL_CIPHER *cipher;
247f5b1c8a1SJohn Marino 
248*de0e0e4dSAntonio Huete Jimenez 	if ((cipher = ssl3_get_cipher(u)) == NULL)
249f5b1c8a1SJohn Marino 		return NULL;
250f5b1c8a1SJohn Marino 
251*de0e0e4dSAntonio Huete Jimenez 	if (cipher->algorithm_enc == SSL_RC4)
252*de0e0e4dSAntonio Huete Jimenez 		return NULL;
253*de0e0e4dSAntonio Huete Jimenez 
254*de0e0e4dSAntonio Huete Jimenez 	return cipher;
255f5b1c8a1SJohn Marino }
256f5b1c8a1SJohn Marino 
257f5b1c8a1SJohn Marino void
dtls1_start_timer(SSL * s)258f5b1c8a1SJohn Marino dtls1_start_timer(SSL *s)
259f5b1c8a1SJohn Marino {
260f5b1c8a1SJohn Marino 
261f5b1c8a1SJohn Marino 	/* If timer is not set, initialize duration with 1 second */
262f5b1c8a1SJohn Marino 	if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) {
263f5b1c8a1SJohn Marino 		s->d1->timeout_duration = 1;
264f5b1c8a1SJohn Marino 	}
265f5b1c8a1SJohn Marino 
266f5b1c8a1SJohn Marino 	/* Set timeout to current time */
267f5b1c8a1SJohn Marino 	gettimeofday(&(s->d1->next_timeout), NULL);
268f5b1c8a1SJohn Marino 
269f5b1c8a1SJohn Marino 	/* Add duration to current time */
270f5b1c8a1SJohn Marino 	s->d1->next_timeout.tv_sec += s->d1->timeout_duration;
271f5b1c8a1SJohn Marino 	BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
27272c33676SMaxim Ag 	    &s->d1->next_timeout);
273f5b1c8a1SJohn Marino }
274f5b1c8a1SJohn Marino 
275f5b1c8a1SJohn Marino struct timeval*
dtls1_get_timeout(SSL * s,struct timeval * timeleft)276f5b1c8a1SJohn Marino dtls1_get_timeout(SSL *s, struct timeval* timeleft)
277f5b1c8a1SJohn Marino {
278f5b1c8a1SJohn Marino 	struct timeval timenow;
279f5b1c8a1SJohn Marino 
280f5b1c8a1SJohn Marino 	/* If no timeout is set, just return NULL */
281f5b1c8a1SJohn Marino 	if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) {
282f5b1c8a1SJohn Marino 		return NULL;
283f5b1c8a1SJohn Marino 	}
284f5b1c8a1SJohn Marino 
285f5b1c8a1SJohn Marino 	/* Get current time */
286f5b1c8a1SJohn Marino 	gettimeofday(&timenow, NULL);
287f5b1c8a1SJohn Marino 
288f5b1c8a1SJohn Marino 	/* If timer already expired, set remaining time to 0 */
289f5b1c8a1SJohn Marino 	if (s->d1->next_timeout.tv_sec < timenow.tv_sec ||
290f5b1c8a1SJohn Marino 	    (s->d1->next_timeout.tv_sec == timenow.tv_sec &&
291f5b1c8a1SJohn Marino 	     s->d1->next_timeout.tv_usec <= timenow.tv_usec)) {
292f5b1c8a1SJohn Marino 		memset(timeleft, 0, sizeof(struct timeval));
293f5b1c8a1SJohn Marino 		return timeleft;
294f5b1c8a1SJohn Marino 	}
295f5b1c8a1SJohn Marino 
296f5b1c8a1SJohn Marino 	/* Calculate time left until timer expires */
297f5b1c8a1SJohn Marino 	memcpy(timeleft, &(s->d1->next_timeout), sizeof(struct timeval));
298f5b1c8a1SJohn Marino 	timeleft->tv_sec -= timenow.tv_sec;
299f5b1c8a1SJohn Marino 	timeleft->tv_usec -= timenow.tv_usec;
300f5b1c8a1SJohn Marino 	if (timeleft->tv_usec < 0) {
301f5b1c8a1SJohn Marino 		timeleft->tv_sec--;
302f5b1c8a1SJohn Marino 		timeleft->tv_usec += 1000000;
303f5b1c8a1SJohn Marino 	}
304f5b1c8a1SJohn Marino 
305f5b1c8a1SJohn Marino 	/* If remaining time is less than 15 ms, set it to 0
306f5b1c8a1SJohn Marino 	 * to prevent issues because of small devergences with
307f5b1c8a1SJohn Marino 	 * socket timeouts.
308f5b1c8a1SJohn Marino 	 */
309f5b1c8a1SJohn Marino 	if (timeleft->tv_sec == 0 && timeleft->tv_usec < 15000) {
310f5b1c8a1SJohn Marino 		memset(timeleft, 0, sizeof(struct timeval));
311f5b1c8a1SJohn Marino 	}
312f5b1c8a1SJohn Marino 
313f5b1c8a1SJohn Marino 
314f5b1c8a1SJohn Marino 	return timeleft;
315f5b1c8a1SJohn Marino }
316f5b1c8a1SJohn Marino 
317f5b1c8a1SJohn Marino int
dtls1_is_timer_expired(SSL * s)318f5b1c8a1SJohn Marino dtls1_is_timer_expired(SSL *s)
319f5b1c8a1SJohn Marino {
320f5b1c8a1SJohn Marino 	struct timeval timeleft;
321f5b1c8a1SJohn Marino 
322f5b1c8a1SJohn Marino 	/* Get time left until timeout, return false if no timer running */
323f5b1c8a1SJohn Marino 	if (dtls1_get_timeout(s, &timeleft) == NULL) {
324f5b1c8a1SJohn Marino 		return 0;
325f5b1c8a1SJohn Marino 	}
326f5b1c8a1SJohn Marino 
327f5b1c8a1SJohn Marino 	/* Return false if timer is not expired yet */
328f5b1c8a1SJohn Marino 	if (timeleft.tv_sec > 0 || timeleft.tv_usec > 0) {
329f5b1c8a1SJohn Marino 		return 0;
330f5b1c8a1SJohn Marino 	}
331f5b1c8a1SJohn Marino 
332f5b1c8a1SJohn Marino 	/* Timer expired, so return true */
333f5b1c8a1SJohn Marino 	return 1;
334f5b1c8a1SJohn Marino }
335f5b1c8a1SJohn Marino 
336f5b1c8a1SJohn Marino void
dtls1_double_timeout(SSL * s)337f5b1c8a1SJohn Marino dtls1_double_timeout(SSL *s)
338f5b1c8a1SJohn Marino {
339f5b1c8a1SJohn Marino 	s->d1->timeout_duration *= 2;
340f5b1c8a1SJohn Marino 	if (s->d1->timeout_duration > 60)
341f5b1c8a1SJohn Marino 		s->d1->timeout_duration = 60;
342f5b1c8a1SJohn Marino 	dtls1_start_timer(s);
343f5b1c8a1SJohn Marino }
344f5b1c8a1SJohn Marino 
345f5b1c8a1SJohn Marino void
dtls1_stop_timer(SSL * s)346f5b1c8a1SJohn Marino dtls1_stop_timer(SSL *s)
347f5b1c8a1SJohn Marino {
348f5b1c8a1SJohn Marino 	/* Reset everything */
349*de0e0e4dSAntonio Huete Jimenez 	memset(&(s->d1->timeout), 0, sizeof(struct dtls1_timeout_st));
350f5b1c8a1SJohn Marino 	memset(&(s->d1->next_timeout), 0, sizeof(struct timeval));
351f5b1c8a1SJohn Marino 	s->d1->timeout_duration = 1;
352f5b1c8a1SJohn Marino 	BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
353f5b1c8a1SJohn Marino 	    &(s->d1->next_timeout));
354f5b1c8a1SJohn Marino 	/* Clear retransmission buffer */
355f5b1c8a1SJohn Marino 	dtls1_clear_record_buffer(s);
356f5b1c8a1SJohn Marino }
357f5b1c8a1SJohn Marino 
358f5b1c8a1SJohn Marino int
dtls1_check_timeout_num(SSL * s)359f5b1c8a1SJohn Marino dtls1_check_timeout_num(SSL *s)
360f5b1c8a1SJohn Marino {
361*de0e0e4dSAntonio Huete Jimenez 	s->d1->timeout.num_alerts++;
362f5b1c8a1SJohn Marino 
363f5b1c8a1SJohn Marino 	/* Reduce MTU after 2 unsuccessful retransmissions */
364*de0e0e4dSAntonio Huete Jimenez 	if (s->d1->timeout.num_alerts > 2) {
365*de0e0e4dSAntonio Huete Jimenez 		s->d1->mtu = BIO_ctrl(SSL_get_wbio(s),
366f5b1c8a1SJohn Marino 		    BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL);
367f5b1c8a1SJohn Marino 
368f5b1c8a1SJohn Marino 	}
369f5b1c8a1SJohn Marino 
370*de0e0e4dSAntonio Huete Jimenez 	if (s->d1->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT) {
371f5b1c8a1SJohn Marino 		/* fail the connection, enough alerts have been sent */
37272c33676SMaxim Ag 		SSLerror(s, SSL_R_READ_TIMEOUT_EXPIRED);
373f5b1c8a1SJohn Marino 		return -1;
374f5b1c8a1SJohn Marino 	}
375f5b1c8a1SJohn Marino 
376f5b1c8a1SJohn Marino 	return 0;
377f5b1c8a1SJohn Marino }
378f5b1c8a1SJohn Marino 
379f5b1c8a1SJohn Marino int
dtls1_handle_timeout(SSL * s)380f5b1c8a1SJohn Marino dtls1_handle_timeout(SSL *s)
381f5b1c8a1SJohn Marino {
382f5b1c8a1SJohn Marino 	/* if no timer is expired, don't do anything */
383f5b1c8a1SJohn Marino 	if (!dtls1_is_timer_expired(s)) {
384f5b1c8a1SJohn Marino 		return 0;
385f5b1c8a1SJohn Marino 	}
386f5b1c8a1SJohn Marino 
387f5b1c8a1SJohn Marino 	dtls1_double_timeout(s);
388f5b1c8a1SJohn Marino 
389f5b1c8a1SJohn Marino 	if (dtls1_check_timeout_num(s) < 0)
390f5b1c8a1SJohn Marino 		return -1;
391f5b1c8a1SJohn Marino 
392*de0e0e4dSAntonio Huete Jimenez 	s->d1->timeout.read_timeouts++;
393*de0e0e4dSAntonio Huete Jimenez 	if (s->d1->timeout.read_timeouts > DTLS1_TMO_READ_COUNT) {
394*de0e0e4dSAntonio Huete Jimenez 		s->d1->timeout.read_timeouts = 1;
395f5b1c8a1SJohn Marino 	}
396f5b1c8a1SJohn Marino 
397f5b1c8a1SJohn Marino 	dtls1_start_timer(s);
398f5b1c8a1SJohn Marino 	return dtls1_retransmit_buffered_messages(s);
399f5b1c8a1SJohn Marino }
400f5b1c8a1SJohn Marino 
401f5b1c8a1SJohn Marino int
dtls1_listen(SSL * s,struct sockaddr * client)402f5b1c8a1SJohn Marino dtls1_listen(SSL *s, struct sockaddr *client)
403f5b1c8a1SJohn Marino {
404f5b1c8a1SJohn Marino 	int ret;
405f5b1c8a1SJohn Marino 
406f5b1c8a1SJohn Marino 	/* Ensure there is no state left over from a previous invocation */
407f5b1c8a1SJohn Marino 	SSL_clear(s);
408f5b1c8a1SJohn Marino 
409f5b1c8a1SJohn Marino 	SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE);
410*de0e0e4dSAntonio Huete Jimenez 	s->d1->listen = 1;
411f5b1c8a1SJohn Marino 
412f5b1c8a1SJohn Marino 	ret = SSL_accept(s);
413f5b1c8a1SJohn Marino 	if (ret <= 0)
414f5b1c8a1SJohn Marino 		return ret;
415f5b1c8a1SJohn Marino 
416f5b1c8a1SJohn Marino 	(void)BIO_dgram_get_peer(SSL_get_rbio(s), client);
417f5b1c8a1SJohn Marino 	return 1;
418f5b1c8a1SJohn Marino }
419