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