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