1ebfedea0SLionel Sambuc /* ssl/d1_lib.c */
2ebfedea0SLionel Sambuc /*
3ebfedea0SLionel Sambuc * DTLS implementation written by Nagendra Modadugu
4ebfedea0SLionel Sambuc * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
5ebfedea0SLionel Sambuc */
6ebfedea0SLionel Sambuc /* ====================================================================
7ebfedea0SLionel Sambuc * Copyright (c) 1999-2005 The OpenSSL Project. All rights reserved.
8ebfedea0SLionel Sambuc *
9ebfedea0SLionel Sambuc * Redistribution and use in source and binary forms, with or without
10ebfedea0SLionel Sambuc * modification, are permitted provided that the following conditions
11ebfedea0SLionel Sambuc * are met:
12ebfedea0SLionel Sambuc *
13ebfedea0SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
14ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer.
15ebfedea0SLionel Sambuc *
16ebfedea0SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
17ebfedea0SLionel Sambuc * notice, this list of conditions and the following disclaimer in
18ebfedea0SLionel Sambuc * the documentation and/or other materials provided with the
19ebfedea0SLionel Sambuc * distribution.
20ebfedea0SLionel Sambuc *
21ebfedea0SLionel Sambuc * 3. All advertising materials mentioning features or use of this
22ebfedea0SLionel Sambuc * software must display the following acknowledgment:
23ebfedea0SLionel Sambuc * "This product includes software developed by the OpenSSL Project
24ebfedea0SLionel Sambuc * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25ebfedea0SLionel Sambuc *
26ebfedea0SLionel Sambuc * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27ebfedea0SLionel Sambuc * endorse or promote products derived from this software without
28ebfedea0SLionel Sambuc * prior written permission. For written permission, please contact
29ebfedea0SLionel Sambuc * openssl-core@OpenSSL.org.
30ebfedea0SLionel Sambuc *
31ebfedea0SLionel Sambuc * 5. Products derived from this software may not be called "OpenSSL"
32ebfedea0SLionel Sambuc * nor may "OpenSSL" appear in their names without prior written
33ebfedea0SLionel Sambuc * permission of the OpenSSL Project.
34ebfedea0SLionel Sambuc *
35ebfedea0SLionel Sambuc * 6. Redistributions of any form whatsoever must retain the following
36ebfedea0SLionel Sambuc * acknowledgment:
37ebfedea0SLionel Sambuc * "This product includes software developed by the OpenSSL Project
38ebfedea0SLionel Sambuc * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39ebfedea0SLionel Sambuc *
40ebfedea0SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41ebfedea0SLionel Sambuc * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42ebfedea0SLionel Sambuc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43ebfedea0SLionel Sambuc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
44ebfedea0SLionel Sambuc * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45ebfedea0SLionel Sambuc * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46ebfedea0SLionel Sambuc * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47ebfedea0SLionel Sambuc * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48ebfedea0SLionel Sambuc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49ebfedea0SLionel Sambuc * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50ebfedea0SLionel Sambuc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51ebfedea0SLionel Sambuc * OF THE POSSIBILITY OF SUCH DAMAGE.
52ebfedea0SLionel Sambuc * ====================================================================
53ebfedea0SLionel Sambuc *
54ebfedea0SLionel Sambuc * This product includes cryptographic software written by Eric Young
55ebfedea0SLionel Sambuc * (eay@cryptsoft.com). This product includes software written by Tim
56ebfedea0SLionel Sambuc * Hudson (tjh@cryptsoft.com).
57ebfedea0SLionel Sambuc *
58ebfedea0SLionel Sambuc */
59ebfedea0SLionel Sambuc
60ebfedea0SLionel Sambuc #include <stdio.h>
61ebfedea0SLionel Sambuc #define USE_SOCKETS
62ebfedea0SLionel Sambuc #include <openssl/objects.h>
63ebfedea0SLionel Sambuc #include "ssl_locl.h"
64ebfedea0SLionel Sambuc
65ebfedea0SLionel Sambuc #if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS)
66ebfedea0SLionel Sambuc # include <sys/timeb.h>
67ebfedea0SLionel Sambuc #endif
68ebfedea0SLionel Sambuc
69ebfedea0SLionel Sambuc static void get_current_time(struct timeval *t);
70ebfedea0SLionel Sambuc const char dtls1_version_str[] = "DTLSv1" OPENSSL_VERSION_PTEXT;
71ebfedea0SLionel Sambuc int dtls1_listen(SSL *s, struct sockaddr *client);
72ebfedea0SLionel Sambuc
73ebfedea0SLionel Sambuc SSL3_ENC_METHOD DTLSv1_enc_data = {
74ebfedea0SLionel Sambuc dtls1_enc,
75ebfedea0SLionel Sambuc tls1_mac,
76ebfedea0SLionel Sambuc tls1_setup_key_block,
77ebfedea0SLionel Sambuc tls1_generate_master_secret,
78ebfedea0SLionel Sambuc tls1_change_cipher_state,
79ebfedea0SLionel Sambuc tls1_final_finish_mac,
80ebfedea0SLionel Sambuc TLS1_FINISH_MAC_LENGTH,
81ebfedea0SLionel Sambuc tls1_cert_verify_mac,
82ebfedea0SLionel Sambuc TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE,
83ebfedea0SLionel Sambuc TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
84ebfedea0SLionel Sambuc tls1_alert_code,
85ebfedea0SLionel Sambuc tls1_export_keying_material,
86ebfedea0SLionel Sambuc };
87ebfedea0SLionel Sambuc
dtls1_default_timeout(void)88ebfedea0SLionel Sambuc long dtls1_default_timeout(void)
89ebfedea0SLionel Sambuc {
90*0a6a1f1dSLionel Sambuc /*
91*0a6a1f1dSLionel Sambuc * 2 hours, the 24 hours mentioned in the DTLSv1 spec is way too long for
92*0a6a1f1dSLionel Sambuc * http, the cache would over fill
93*0a6a1f1dSLionel Sambuc */
94ebfedea0SLionel Sambuc return (60 * 60 * 2);
95ebfedea0SLionel Sambuc }
96ebfedea0SLionel Sambuc
dtls1_new(SSL * s)97ebfedea0SLionel Sambuc int dtls1_new(SSL *s)
98ebfedea0SLionel Sambuc {
99ebfedea0SLionel Sambuc DTLS1_STATE *d1;
100ebfedea0SLionel Sambuc
101*0a6a1f1dSLionel Sambuc if (!ssl3_new(s))
102*0a6a1f1dSLionel Sambuc return (0);
103*0a6a1f1dSLionel Sambuc if ((d1 = OPENSSL_malloc(sizeof *d1)) == NULL)
104*0a6a1f1dSLionel Sambuc return (0);
105ebfedea0SLionel Sambuc memset(d1, 0, sizeof *d1);
106ebfedea0SLionel Sambuc
107ebfedea0SLionel Sambuc /* d1->handshake_epoch=0; */
108ebfedea0SLionel Sambuc
109ebfedea0SLionel Sambuc d1->unprocessed_rcds.q = pqueue_new();
110ebfedea0SLionel Sambuc d1->processed_rcds.q = pqueue_new();
111ebfedea0SLionel Sambuc d1->buffered_messages = pqueue_new();
112ebfedea0SLionel Sambuc d1->sent_messages = pqueue_new();
113ebfedea0SLionel Sambuc d1->buffered_app_data.q = pqueue_new();
114ebfedea0SLionel Sambuc
115*0a6a1f1dSLionel Sambuc if (s->server) {
116ebfedea0SLionel Sambuc d1->cookie_len = sizeof(s->d1->cookie);
117ebfedea0SLionel Sambuc }
118ebfedea0SLionel Sambuc
119*0a6a1f1dSLionel Sambuc d1->link_mtu = 0;
120*0a6a1f1dSLionel Sambuc d1->mtu = 0;
121*0a6a1f1dSLionel Sambuc
122ebfedea0SLionel Sambuc if (!d1->unprocessed_rcds.q || !d1->processed_rcds.q
123*0a6a1f1dSLionel Sambuc || !d1->buffered_messages || !d1->sent_messages
124*0a6a1f1dSLionel Sambuc || !d1->buffered_app_data.q) {
125*0a6a1f1dSLionel Sambuc if (d1->unprocessed_rcds.q)
126*0a6a1f1dSLionel Sambuc pqueue_free(d1->unprocessed_rcds.q);
127*0a6a1f1dSLionel Sambuc if (d1->processed_rcds.q)
128*0a6a1f1dSLionel Sambuc pqueue_free(d1->processed_rcds.q);
129*0a6a1f1dSLionel Sambuc if (d1->buffered_messages)
130*0a6a1f1dSLionel Sambuc pqueue_free(d1->buffered_messages);
131*0a6a1f1dSLionel Sambuc if (d1->sent_messages)
132*0a6a1f1dSLionel Sambuc pqueue_free(d1->sent_messages);
133*0a6a1f1dSLionel Sambuc if (d1->buffered_app_data.q)
134*0a6a1f1dSLionel Sambuc pqueue_free(d1->buffered_app_data.q);
135ebfedea0SLionel Sambuc OPENSSL_free(d1);
136ebfedea0SLionel Sambuc return (0);
137ebfedea0SLionel Sambuc }
138ebfedea0SLionel Sambuc
139ebfedea0SLionel Sambuc s->d1 = d1;
140ebfedea0SLionel Sambuc s->method->ssl_clear(s);
141ebfedea0SLionel Sambuc return (1);
142ebfedea0SLionel Sambuc }
143ebfedea0SLionel Sambuc
dtls1_clear_queues(SSL * s)144ebfedea0SLionel Sambuc static void dtls1_clear_queues(SSL *s)
145ebfedea0SLionel Sambuc {
146ebfedea0SLionel Sambuc pitem *item = NULL;
147ebfedea0SLionel Sambuc hm_fragment *frag = NULL;
148ebfedea0SLionel Sambuc DTLS1_RECORD_DATA *rdata;
149ebfedea0SLionel Sambuc
150*0a6a1f1dSLionel Sambuc while ((item = pqueue_pop(s->d1->unprocessed_rcds.q)) != NULL) {
151ebfedea0SLionel Sambuc rdata = (DTLS1_RECORD_DATA *)item->data;
152*0a6a1f1dSLionel Sambuc if (rdata->rbuf.buf) {
153ebfedea0SLionel Sambuc OPENSSL_free(rdata->rbuf.buf);
154ebfedea0SLionel Sambuc }
155ebfedea0SLionel Sambuc OPENSSL_free(item->data);
156ebfedea0SLionel Sambuc pitem_free(item);
157ebfedea0SLionel Sambuc }
158ebfedea0SLionel Sambuc
159*0a6a1f1dSLionel Sambuc while ((item = pqueue_pop(s->d1->processed_rcds.q)) != NULL) {
160ebfedea0SLionel Sambuc rdata = (DTLS1_RECORD_DATA *)item->data;
161*0a6a1f1dSLionel Sambuc if (rdata->rbuf.buf) {
162ebfedea0SLionel Sambuc OPENSSL_free(rdata->rbuf.buf);
163ebfedea0SLionel Sambuc }
164ebfedea0SLionel Sambuc OPENSSL_free(item->data);
165ebfedea0SLionel Sambuc pitem_free(item);
166ebfedea0SLionel Sambuc }
167ebfedea0SLionel Sambuc
168*0a6a1f1dSLionel Sambuc while ((item = pqueue_pop(s->d1->buffered_messages)) != NULL) {
169ebfedea0SLionel Sambuc frag = (hm_fragment *)item->data;
170*0a6a1f1dSLionel Sambuc dtls1_hm_fragment_free(frag);
171ebfedea0SLionel Sambuc pitem_free(item);
172ebfedea0SLionel Sambuc }
173ebfedea0SLionel Sambuc
174*0a6a1f1dSLionel Sambuc while ((item = pqueue_pop(s->d1->sent_messages)) != NULL) {
175ebfedea0SLionel Sambuc frag = (hm_fragment *)item->data;
176*0a6a1f1dSLionel Sambuc dtls1_hm_fragment_free(frag);
177ebfedea0SLionel Sambuc pitem_free(item);
178ebfedea0SLionel Sambuc }
179ebfedea0SLionel Sambuc
180*0a6a1f1dSLionel Sambuc while ((item = pqueue_pop(s->d1->buffered_app_data.q)) != NULL) {
181*0a6a1f1dSLionel Sambuc rdata = (DTLS1_RECORD_DATA *)item->data;
182*0a6a1f1dSLionel Sambuc if (rdata->rbuf.buf) {
183*0a6a1f1dSLionel Sambuc OPENSSL_free(rdata->rbuf.buf);
184*0a6a1f1dSLionel Sambuc }
185*0a6a1f1dSLionel Sambuc OPENSSL_free(item->data);
186ebfedea0SLionel Sambuc pitem_free(item);
187ebfedea0SLionel Sambuc }
188ebfedea0SLionel Sambuc }
189ebfedea0SLionel Sambuc
dtls1_free(SSL * s)190ebfedea0SLionel Sambuc void dtls1_free(SSL *s)
191ebfedea0SLionel Sambuc {
192ebfedea0SLionel Sambuc ssl3_free(s);
193ebfedea0SLionel Sambuc
194ebfedea0SLionel Sambuc dtls1_clear_queues(s);
195ebfedea0SLionel Sambuc
196ebfedea0SLionel Sambuc pqueue_free(s->d1->unprocessed_rcds.q);
197ebfedea0SLionel Sambuc pqueue_free(s->d1->processed_rcds.q);
198ebfedea0SLionel Sambuc pqueue_free(s->d1->buffered_messages);
199ebfedea0SLionel Sambuc pqueue_free(s->d1->sent_messages);
200ebfedea0SLionel Sambuc pqueue_free(s->d1->buffered_app_data.q);
201ebfedea0SLionel Sambuc
202ebfedea0SLionel Sambuc OPENSSL_free(s->d1);
203*0a6a1f1dSLionel Sambuc s->d1 = NULL;
204ebfedea0SLionel Sambuc }
205ebfedea0SLionel Sambuc
dtls1_clear(SSL * s)206ebfedea0SLionel Sambuc void dtls1_clear(SSL *s)
207ebfedea0SLionel Sambuc {
208ebfedea0SLionel Sambuc pqueue unprocessed_rcds;
209ebfedea0SLionel Sambuc pqueue processed_rcds;
210ebfedea0SLionel Sambuc pqueue buffered_messages;
211ebfedea0SLionel Sambuc pqueue sent_messages;
212ebfedea0SLionel Sambuc pqueue buffered_app_data;
213ebfedea0SLionel Sambuc unsigned int mtu;
214*0a6a1f1dSLionel Sambuc unsigned int link_mtu;
215ebfedea0SLionel Sambuc
216*0a6a1f1dSLionel Sambuc if (s->d1) {
217ebfedea0SLionel Sambuc unprocessed_rcds = s->d1->unprocessed_rcds.q;
218ebfedea0SLionel Sambuc processed_rcds = s->d1->processed_rcds.q;
219ebfedea0SLionel Sambuc buffered_messages = s->d1->buffered_messages;
220ebfedea0SLionel Sambuc sent_messages = s->d1->sent_messages;
221ebfedea0SLionel Sambuc buffered_app_data = s->d1->buffered_app_data.q;
222ebfedea0SLionel Sambuc mtu = s->d1->mtu;
223*0a6a1f1dSLionel Sambuc link_mtu = s->d1->link_mtu;
224ebfedea0SLionel Sambuc
225ebfedea0SLionel Sambuc dtls1_clear_queues(s);
226ebfedea0SLionel Sambuc
227ebfedea0SLionel Sambuc memset(s->d1, 0, sizeof(*(s->d1)));
228ebfedea0SLionel Sambuc
229*0a6a1f1dSLionel Sambuc if (s->server) {
230ebfedea0SLionel Sambuc s->d1->cookie_len = sizeof(s->d1->cookie);
231ebfedea0SLionel Sambuc }
232ebfedea0SLionel Sambuc
233*0a6a1f1dSLionel Sambuc if (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU) {
234ebfedea0SLionel Sambuc s->d1->mtu = mtu;
235*0a6a1f1dSLionel Sambuc s->d1->link_mtu = link_mtu;
236ebfedea0SLionel Sambuc }
237ebfedea0SLionel Sambuc
238ebfedea0SLionel Sambuc s->d1->unprocessed_rcds.q = unprocessed_rcds;
239ebfedea0SLionel Sambuc s->d1->processed_rcds.q = processed_rcds;
240ebfedea0SLionel Sambuc s->d1->buffered_messages = buffered_messages;
241ebfedea0SLionel Sambuc s->d1->sent_messages = sent_messages;
242ebfedea0SLionel Sambuc s->d1->buffered_app_data.q = buffered_app_data;
243ebfedea0SLionel Sambuc }
244ebfedea0SLionel Sambuc
245ebfedea0SLionel Sambuc ssl3_clear(s);
246ebfedea0SLionel Sambuc if (s->options & SSL_OP_CISCO_ANYCONNECT)
247ebfedea0SLionel Sambuc s->version = DTLS1_BAD_VER;
248ebfedea0SLionel Sambuc else
249ebfedea0SLionel Sambuc s->version = DTLS1_VERSION;
250ebfedea0SLionel Sambuc }
251ebfedea0SLionel Sambuc
dtls1_ctrl(SSL * s,int cmd,long larg,void * parg)252ebfedea0SLionel Sambuc long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg)
253ebfedea0SLionel Sambuc {
254ebfedea0SLionel Sambuc int ret = 0;
255ebfedea0SLionel Sambuc
256*0a6a1f1dSLionel Sambuc switch (cmd) {
257ebfedea0SLionel Sambuc case DTLS_CTRL_GET_TIMEOUT:
258*0a6a1f1dSLionel Sambuc if (dtls1_get_timeout(s, (struct timeval *)parg) != NULL) {
259ebfedea0SLionel Sambuc ret = 1;
260ebfedea0SLionel Sambuc }
261ebfedea0SLionel Sambuc break;
262ebfedea0SLionel Sambuc case DTLS_CTRL_HANDLE_TIMEOUT:
263ebfedea0SLionel Sambuc ret = dtls1_handle_timeout(s);
264ebfedea0SLionel Sambuc break;
265ebfedea0SLionel Sambuc case DTLS_CTRL_LISTEN:
266ebfedea0SLionel Sambuc ret = dtls1_listen(s, parg);
267ebfedea0SLionel Sambuc break;
268*0a6a1f1dSLionel Sambuc case SSL_CTRL_CHECK_PROTO_VERSION:
269*0a6a1f1dSLionel Sambuc /*
270*0a6a1f1dSLionel Sambuc * For library-internal use; checks that the current protocol is the
271*0a6a1f1dSLionel Sambuc * highest enabled version (according to s->ctx->method, as version
272*0a6a1f1dSLionel Sambuc * negotiation may have changed s->method).
273*0a6a1f1dSLionel Sambuc */
274*0a6a1f1dSLionel Sambuc #if DTLS_MAX_VERSION != DTLS1_VERSION
275*0a6a1f1dSLionel Sambuc # error Code needs update for DTLS_method() support beyond DTLS1_VERSION.
276*0a6a1f1dSLionel Sambuc #endif
277*0a6a1f1dSLionel Sambuc /*
278*0a6a1f1dSLionel Sambuc * Just one protocol version is supported so far; fail closed if the
279*0a6a1f1dSLionel Sambuc * version is not as expected.
280*0a6a1f1dSLionel Sambuc */
281*0a6a1f1dSLionel Sambuc return s->version == DTLS_MAX_VERSION;
282*0a6a1f1dSLionel Sambuc case DTLS_CTRL_SET_LINK_MTU:
283*0a6a1f1dSLionel Sambuc if (larg < (long)dtls1_link_min_mtu())
284*0a6a1f1dSLionel Sambuc return 0;
285*0a6a1f1dSLionel Sambuc s->d1->link_mtu = larg;
286*0a6a1f1dSLionel Sambuc return 1;
287*0a6a1f1dSLionel Sambuc case DTLS_CTRL_GET_LINK_MIN_MTU:
288*0a6a1f1dSLionel Sambuc return (long)dtls1_link_min_mtu();
289*0a6a1f1dSLionel Sambuc case SSL_CTRL_SET_MTU:
290*0a6a1f1dSLionel Sambuc /*
291*0a6a1f1dSLionel Sambuc * We may not have a BIO set yet so can't call dtls1_min_mtu()
292*0a6a1f1dSLionel Sambuc * We'll have to make do with dtls1_link_min_mtu() and max overhead
293*0a6a1f1dSLionel Sambuc */
294*0a6a1f1dSLionel Sambuc if (larg < (long)dtls1_link_min_mtu() - DTLS1_MAX_MTU_OVERHEAD)
295*0a6a1f1dSLionel Sambuc return 0;
296*0a6a1f1dSLionel Sambuc s->d1->mtu = larg;
297*0a6a1f1dSLionel Sambuc return larg;
298ebfedea0SLionel Sambuc default:
299ebfedea0SLionel Sambuc ret = ssl3_ctrl(s, cmd, larg, parg);
300ebfedea0SLionel Sambuc break;
301ebfedea0SLionel Sambuc }
302ebfedea0SLionel Sambuc return (ret);
303ebfedea0SLionel Sambuc }
304ebfedea0SLionel Sambuc
305ebfedea0SLionel Sambuc /*
306ebfedea0SLionel Sambuc * As it's impossible to use stream ciphers in "datagram" mode, this
307ebfedea0SLionel Sambuc * simple filter is designed to disengage them in DTLS. Unfortunately
308ebfedea0SLionel Sambuc * there is no universal way to identify stream SSL_CIPHER, so we have
309ebfedea0SLionel Sambuc * to explicitly list their SSL_* codes. Currently RC4 is the only one
310ebfedea0SLionel Sambuc * available, but if new ones emerge, they will have to be added...
311ebfedea0SLionel Sambuc */
dtls1_get_cipher(unsigned int u)312ebfedea0SLionel Sambuc const SSL_CIPHER *dtls1_get_cipher(unsigned int u)
313ebfedea0SLionel Sambuc {
314ebfedea0SLionel Sambuc const SSL_CIPHER *ciph = ssl3_get_cipher(u);
315ebfedea0SLionel Sambuc
316*0a6a1f1dSLionel Sambuc if (ciph != NULL) {
317ebfedea0SLionel Sambuc if (ciph->algorithm_enc == SSL_RC4)
318ebfedea0SLionel Sambuc return NULL;
319ebfedea0SLionel Sambuc }
320ebfedea0SLionel Sambuc
321ebfedea0SLionel Sambuc return ciph;
322ebfedea0SLionel Sambuc }
323ebfedea0SLionel Sambuc
dtls1_start_timer(SSL * s)324ebfedea0SLionel Sambuc void dtls1_start_timer(SSL *s)
325ebfedea0SLionel Sambuc {
326ebfedea0SLionel Sambuc #ifndef OPENSSL_NO_SCTP
327ebfedea0SLionel Sambuc /* Disable timer for SCTP */
328*0a6a1f1dSLionel Sambuc if (BIO_dgram_is_sctp(SSL_get_wbio(s))) {
329ebfedea0SLionel Sambuc memset(&(s->d1->next_timeout), 0, sizeof(struct timeval));
330ebfedea0SLionel Sambuc return;
331ebfedea0SLionel Sambuc }
332ebfedea0SLionel Sambuc #endif
333ebfedea0SLionel Sambuc
334ebfedea0SLionel Sambuc /* If timer is not set, initialize duration with 1 second */
335*0a6a1f1dSLionel Sambuc if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) {
336ebfedea0SLionel Sambuc s->d1->timeout_duration = 1;
337ebfedea0SLionel Sambuc }
338ebfedea0SLionel Sambuc
339ebfedea0SLionel Sambuc /* Set timeout to current time */
340ebfedea0SLionel Sambuc get_current_time(&(s->d1->next_timeout));
341ebfedea0SLionel Sambuc
342ebfedea0SLionel Sambuc /* Add duration to current time */
343ebfedea0SLionel Sambuc s->d1->next_timeout.tv_sec += s->d1->timeout_duration;
344*0a6a1f1dSLionel Sambuc BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
345*0a6a1f1dSLionel Sambuc &(s->d1->next_timeout));
346ebfedea0SLionel Sambuc }
347ebfedea0SLionel Sambuc
dtls1_get_timeout(SSL * s,struct timeval * timeleft)348ebfedea0SLionel Sambuc struct timeval *dtls1_get_timeout(SSL *s, struct timeval *timeleft)
349ebfedea0SLionel Sambuc {
350ebfedea0SLionel Sambuc struct timeval timenow;
351ebfedea0SLionel Sambuc
352ebfedea0SLionel Sambuc /* If no timeout is set, just return NULL */
353*0a6a1f1dSLionel Sambuc if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) {
354ebfedea0SLionel Sambuc return NULL;
355ebfedea0SLionel Sambuc }
356ebfedea0SLionel Sambuc
357ebfedea0SLionel Sambuc /* Get current time */
358ebfedea0SLionel Sambuc get_current_time(&timenow);
359ebfedea0SLionel Sambuc
360ebfedea0SLionel Sambuc /* If timer already expired, set remaining time to 0 */
361ebfedea0SLionel Sambuc if (s->d1->next_timeout.tv_sec < timenow.tv_sec ||
362ebfedea0SLionel Sambuc (s->d1->next_timeout.tv_sec == timenow.tv_sec &&
363*0a6a1f1dSLionel Sambuc s->d1->next_timeout.tv_usec <= timenow.tv_usec)) {
364ebfedea0SLionel Sambuc memset(timeleft, 0, sizeof(struct timeval));
365ebfedea0SLionel Sambuc return timeleft;
366ebfedea0SLionel Sambuc }
367ebfedea0SLionel Sambuc
368ebfedea0SLionel Sambuc /* Calculate time left until timer expires */
369ebfedea0SLionel Sambuc memcpy(timeleft, &(s->d1->next_timeout), sizeof(struct timeval));
370ebfedea0SLionel Sambuc timeleft->tv_sec -= timenow.tv_sec;
371ebfedea0SLionel Sambuc timeleft->tv_usec -= timenow.tv_usec;
372*0a6a1f1dSLionel Sambuc if (timeleft->tv_usec < 0) {
373ebfedea0SLionel Sambuc timeleft->tv_sec--;
374ebfedea0SLionel Sambuc timeleft->tv_usec += 1000000;
375ebfedea0SLionel Sambuc }
376ebfedea0SLionel Sambuc
377*0a6a1f1dSLionel Sambuc /*
378*0a6a1f1dSLionel Sambuc * If remaining time is less than 15 ms, set it to 0 to prevent issues
379*0a6a1f1dSLionel Sambuc * because of small devergences with socket timeouts.
380ebfedea0SLionel Sambuc */
381*0a6a1f1dSLionel Sambuc if (timeleft->tv_sec == 0 && timeleft->tv_usec < 15000) {
382ebfedea0SLionel Sambuc memset(timeleft, 0, sizeof(struct timeval));
383ebfedea0SLionel Sambuc }
384ebfedea0SLionel Sambuc
385ebfedea0SLionel Sambuc return timeleft;
386ebfedea0SLionel Sambuc }
387ebfedea0SLionel Sambuc
dtls1_is_timer_expired(SSL * s)388ebfedea0SLionel Sambuc int dtls1_is_timer_expired(SSL *s)
389ebfedea0SLionel Sambuc {
390ebfedea0SLionel Sambuc struct timeval timeleft;
391ebfedea0SLionel Sambuc
392ebfedea0SLionel Sambuc /* Get time left until timeout, return false if no timer running */
393*0a6a1f1dSLionel Sambuc if (dtls1_get_timeout(s, &timeleft) == NULL) {
394ebfedea0SLionel Sambuc return 0;
395ebfedea0SLionel Sambuc }
396ebfedea0SLionel Sambuc
397ebfedea0SLionel Sambuc /* Return false if timer is not expired yet */
398*0a6a1f1dSLionel Sambuc if (timeleft.tv_sec > 0 || timeleft.tv_usec > 0) {
399ebfedea0SLionel Sambuc return 0;
400ebfedea0SLionel Sambuc }
401ebfedea0SLionel Sambuc
402ebfedea0SLionel Sambuc /* Timer expired, so return true */
403ebfedea0SLionel Sambuc return 1;
404ebfedea0SLionel Sambuc }
405ebfedea0SLionel Sambuc
dtls1_double_timeout(SSL * s)406ebfedea0SLionel Sambuc void dtls1_double_timeout(SSL *s)
407ebfedea0SLionel Sambuc {
408ebfedea0SLionel Sambuc s->d1->timeout_duration *= 2;
409ebfedea0SLionel Sambuc if (s->d1->timeout_duration > 60)
410ebfedea0SLionel Sambuc s->d1->timeout_duration = 60;
411ebfedea0SLionel Sambuc dtls1_start_timer(s);
412ebfedea0SLionel Sambuc }
413ebfedea0SLionel Sambuc
dtls1_stop_timer(SSL * s)414ebfedea0SLionel Sambuc void dtls1_stop_timer(SSL *s)
415ebfedea0SLionel Sambuc {
416ebfedea0SLionel Sambuc /* Reset everything */
417ebfedea0SLionel Sambuc memset(&(s->d1->timeout), 0, sizeof(struct dtls1_timeout_st));
418ebfedea0SLionel Sambuc memset(&(s->d1->next_timeout), 0, sizeof(struct timeval));
419ebfedea0SLionel Sambuc s->d1->timeout_duration = 1;
420*0a6a1f1dSLionel Sambuc BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
421*0a6a1f1dSLionel Sambuc &(s->d1->next_timeout));
422ebfedea0SLionel Sambuc /* Clear retransmission buffer */
423ebfedea0SLionel Sambuc dtls1_clear_record_buffer(s);
424ebfedea0SLionel Sambuc }
425ebfedea0SLionel Sambuc
dtls1_check_timeout_num(SSL * s)426ebfedea0SLionel Sambuc int dtls1_check_timeout_num(SSL *s)
427ebfedea0SLionel Sambuc {
428*0a6a1f1dSLionel Sambuc unsigned int mtu;
429*0a6a1f1dSLionel Sambuc
430ebfedea0SLionel Sambuc s->d1->timeout.num_alerts++;
431ebfedea0SLionel Sambuc
432ebfedea0SLionel Sambuc /* Reduce MTU after 2 unsuccessful retransmissions */
433*0a6a1f1dSLionel Sambuc if (s->d1->timeout.num_alerts > 2
434*0a6a1f1dSLionel Sambuc && !(SSL_get_options(s) & SSL_OP_NO_QUERY_MTU)) {
435*0a6a1f1dSLionel Sambuc mtu =
436*0a6a1f1dSLionel Sambuc BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0,
437*0a6a1f1dSLionel Sambuc NULL);
438*0a6a1f1dSLionel Sambuc if (mtu < s->d1->mtu)
439*0a6a1f1dSLionel Sambuc s->d1->mtu = mtu;
440ebfedea0SLionel Sambuc }
441ebfedea0SLionel Sambuc
442*0a6a1f1dSLionel Sambuc if (s->d1->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT) {
443ebfedea0SLionel Sambuc /* fail the connection, enough alerts have been sent */
444ebfedea0SLionel Sambuc SSLerr(SSL_F_DTLS1_CHECK_TIMEOUT_NUM, SSL_R_READ_TIMEOUT_EXPIRED);
445ebfedea0SLionel Sambuc return -1;
446ebfedea0SLionel Sambuc }
447ebfedea0SLionel Sambuc
448ebfedea0SLionel Sambuc return 0;
449ebfedea0SLionel Sambuc }
450ebfedea0SLionel Sambuc
dtls1_handle_timeout(SSL * s)451ebfedea0SLionel Sambuc int dtls1_handle_timeout(SSL *s)
452ebfedea0SLionel Sambuc {
453ebfedea0SLionel Sambuc /* if no timer is expired, don't do anything */
454*0a6a1f1dSLionel Sambuc if (!dtls1_is_timer_expired(s)) {
455ebfedea0SLionel Sambuc return 0;
456ebfedea0SLionel Sambuc }
457ebfedea0SLionel Sambuc
458ebfedea0SLionel Sambuc dtls1_double_timeout(s);
459ebfedea0SLionel Sambuc
460ebfedea0SLionel Sambuc if (dtls1_check_timeout_num(s) < 0)
461ebfedea0SLionel Sambuc return -1;
462ebfedea0SLionel Sambuc
463ebfedea0SLionel Sambuc s->d1->timeout.read_timeouts++;
464*0a6a1f1dSLionel Sambuc if (s->d1->timeout.read_timeouts > DTLS1_TMO_READ_COUNT) {
465ebfedea0SLionel Sambuc s->d1->timeout.read_timeouts = 1;
466ebfedea0SLionel Sambuc }
467ebfedea0SLionel Sambuc #ifndef OPENSSL_NO_HEARTBEATS
468*0a6a1f1dSLionel Sambuc if (s->tlsext_hb_pending) {
469ebfedea0SLionel Sambuc s->tlsext_hb_pending = 0;
470ebfedea0SLionel Sambuc return dtls1_heartbeat(s);
471ebfedea0SLionel Sambuc }
472ebfedea0SLionel Sambuc #endif
473ebfedea0SLionel Sambuc
474ebfedea0SLionel Sambuc dtls1_start_timer(s);
475ebfedea0SLionel Sambuc return dtls1_retransmit_buffered_messages(s);
476ebfedea0SLionel Sambuc }
477ebfedea0SLionel Sambuc
get_current_time(struct timeval * t)478ebfedea0SLionel Sambuc static void get_current_time(struct timeval *t)
479ebfedea0SLionel Sambuc {
480ebfedea0SLionel Sambuc #ifdef OPENSSL_SYS_WIN32
481ebfedea0SLionel Sambuc struct _timeb tb;
482ebfedea0SLionel Sambuc _ftime(&tb);
483ebfedea0SLionel Sambuc t->tv_sec = (long)tb.time;
484ebfedea0SLionel Sambuc t->tv_usec = (long)tb.millitm * 1000;
485ebfedea0SLionel Sambuc #elif defined(OPENSSL_SYS_VMS)
486ebfedea0SLionel Sambuc struct timeb tb;
487ebfedea0SLionel Sambuc ftime(&tb);
488ebfedea0SLionel Sambuc t->tv_sec = (long)tb.time;
489ebfedea0SLionel Sambuc t->tv_usec = (long)tb.millitm * 1000;
490ebfedea0SLionel Sambuc #else
491ebfedea0SLionel Sambuc gettimeofday(t, NULL);
492ebfedea0SLionel Sambuc #endif
493ebfedea0SLionel Sambuc }
494ebfedea0SLionel Sambuc
dtls1_listen(SSL * s,struct sockaddr * client)495ebfedea0SLionel Sambuc int dtls1_listen(SSL *s, struct sockaddr *client)
496ebfedea0SLionel Sambuc {
497ebfedea0SLionel Sambuc int ret;
498ebfedea0SLionel Sambuc
499*0a6a1f1dSLionel Sambuc /* Ensure there is no state left over from a previous invocation */
500*0a6a1f1dSLionel Sambuc SSL_clear(s);
501*0a6a1f1dSLionel Sambuc
502ebfedea0SLionel Sambuc SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE);
503ebfedea0SLionel Sambuc s->d1->listen = 1;
504ebfedea0SLionel Sambuc
505ebfedea0SLionel Sambuc ret = SSL_accept(s);
506*0a6a1f1dSLionel Sambuc if (ret <= 0)
507*0a6a1f1dSLionel Sambuc return ret;
508ebfedea0SLionel Sambuc
509ebfedea0SLionel Sambuc (void)BIO_dgram_get_peer(SSL_get_rbio(s), client);
510ebfedea0SLionel Sambuc return 1;
511ebfedea0SLionel Sambuc }
512