xref: /minix/crypto/external/bsd/openssl/dist/ssl/d1_lib.c (revision 0a6a1f1d)
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