add callback handler for setting DTLS timer interval

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Bernd Edlinger <bernd.edlinger@hotmail.de>
(Merged from https://github.com/openssl/openssl/pull/4011)
This commit is contained in:
Alfred E. Heggestad 2017-09-06 08:30:00 +02:00 committed by Bernd Edlinger
parent 94b5d7aae9
commit fa4b82cc7c
7 changed files with 114 additions and 9 deletions

View file

@ -0,0 +1,40 @@
=pod
=head1 NAME
DTLS_timer_cb,
DTLS_set_timer_cb
- Set callback for controlling DTLS timer duration
=head1 SYNOPSIS
#include <openssl/ssl.h>
typedef unsigned int (*DTLS_timer_cb)(SSL *s, unsigned int timer_us);
void DTLS_set_timer_cb(SSL *s, DTLS_timer_cb cb);
=head1 DESCRIPTION
This function sets an optional callback function for controlling the
timeout interval on the DTLS protocol. The callback function will be
called by DTLS for every new DTLS packet that is sent.
=head1 RETURN VALUES
Returns void.
=head1 HISTORY
This function was added in OpenSSL 1.1.1
=head1 COPYRIGHT
Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut

View file

@ -2260,6 +2260,12 @@ extern const char SSL_version_str[];
int ERR_load_SSL_strings(void);
typedef unsigned int (*DTLS_timer_cb)(SSL *s, unsigned int timer_us);
void DTLS_set_timer_cb(SSL *s, DTLS_timer_cb cb);
# ifdef __cplusplus
}
# endif

View file

@ -161,6 +161,8 @@ int dtls1_clear(SSL *s)
DTLS_RECORD_LAYER_clear(&s->rlayer);
if (s->d1) {
DTLS_timer_cb timer_cb = s->d1->timer_cb;
buffered_messages = s->d1->buffered_messages;
sent_messages = s->d1->sent_messages;
mtu = s->d1->mtu;
@ -170,6 +172,9 @@ int dtls1_clear(SSL *s)
memset(s->d1, 0, sizeof(*s->d1));
/* Restore the timer callback from previous state */
s->d1->timer_cb = timer_cb;
if (s->server) {
s->d1->cookie_len = sizeof(s->d1->cookie);
}
@ -236,6 +241,8 @@ long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg)
void dtls1_start_timer(SSL *s)
{
unsigned int sec, usec;
#ifndef OPENSSL_NO_SCTP
/* Disable timer for SCTP */
if (BIO_dgram_is_sctp(SSL_get_wbio(s))) {
@ -244,16 +251,34 @@ void dtls1_start_timer(SSL *s)
}
#endif
/* If timer is not set, initialize duration with 1 second */
/*
* If timer is not set, initialize duration with 1 second or
* a user-specified value if the timer callback is installed.
*/
if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) {
s->d1->timeout_duration = 1;
if (s->d1->timer_cb != NULL)
s->d1->timeout_duration_us = s->d1->timer_cb(s, 0);
else
s->d1->timeout_duration_us = 1000000;
}
/* Set timeout to current time */
get_current_time(&(s->d1->next_timeout));
/* Add duration to current time */
s->d1->next_timeout.tv_sec += s->d1->timeout_duration;
sec = s->d1->timeout_duration_us / 1000000;
usec = s->d1->timeout_duration_us - (sec * 1000000);
s->d1->next_timeout.tv_sec += sec;
s->d1->next_timeout.tv_usec += usec;
if (s->d1->next_timeout.tv_usec >= 1000000) {
s->d1->next_timeout.tv_sec++;
s->d1->next_timeout.tv_usec -= 1000000;
}
BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
&(s->d1->next_timeout));
}
@ -318,9 +343,9 @@ int dtls1_is_timer_expired(SSL *s)
void dtls1_double_timeout(SSL *s)
{
s->d1->timeout_duration *= 2;
if (s->d1->timeout_duration > 60)
s->d1->timeout_duration = 60;
s->d1->timeout_duration_us *= 2;
if (s->d1->timeout_duration_us > 60000000)
s->d1->timeout_duration_us = 60000000;
dtls1_start_timer(s);
}
@ -329,7 +354,7 @@ void dtls1_stop_timer(SSL *s)
/* Reset everything */
memset(&s->d1->timeout, 0, sizeof(s->d1->timeout));
memset(&s->d1->next_timeout, 0, sizeof(s->d1->next_timeout));
s->d1->timeout_duration = 1;
s->d1->timeout_duration_us = 1000000;
BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
&(s->d1->next_timeout));
/* Clear retransmission buffer */
@ -367,7 +392,10 @@ int dtls1_handle_timeout(SSL *s)
return 0;
}
dtls1_double_timeout(s);
if (s->d1->timer_cb != NULL)
s->d1->timeout_duration_us = s->d1->timer_cb(s, s->d1->timeout_duration_us);
else
dtls1_double_timeout(s);
if (dtls1_check_timeout_num(s) < 0)
return -1;
@ -952,3 +980,8 @@ size_t DTLS_get_data_mtu(const SSL *s)
return mtu;
}
void DTLS_set_timer_cb(SSL *s, DTLS_timer_cb cb)
{
s->d1->timer_cb = cb;
}

View file

@ -1624,11 +1624,15 @@ typedef struct dtls1_state_st {
*/
struct timeval next_timeout;
/* Timeout duration */
unsigned short timeout_duration;
unsigned int timeout_duration_us;
unsigned int retransmitting;
# ifndef OPENSSL_NO_SCTP
int shutdown_received;
# endif
DTLS_timer_cb timer_cb;
} DTLS1_STATE;
# ifndef OPENSSL_NO_EC

View file

@ -17,6 +17,7 @@
static char *cert = NULL;
static char *privkey = NULL;
static unsigned int timer_cb_count;
#define NUM_TESTS 2
@ -40,6 +41,16 @@ static unsigned char certstatus[] = {
#define RECORD_SEQUENCE 10
static unsigned int timer_cb(SSL *s, unsigned int timer_us)
{
++timer_cb_count;
if (timer_us == 0)
return 1000000;
else
return 2 * timer_us;
}
static int test_dtls_unprocessed(int testidx)
{
SSL_CTX *sctx = NULL, *cctx = NULL;
@ -47,6 +58,8 @@ static int test_dtls_unprocessed(int testidx)
BIO *c_to_s_fbio, *c_to_s_mempacket;
int testresult = 0;
timer_cb_count = 0;
if (!TEST_true(create_ssl_ctx_pair(DTLS_server_method(),
DTLS_client_method(), &sctx,
&cctx, cert, privkey)))
@ -64,6 +77,8 @@ static int test_dtls_unprocessed(int testidx)
NULL, c_to_s_fbio)))
goto end;
DTLS_set_timer_cb(clientssl1, timer_cb);
if (testidx == 1)
certstatus[RECORD_SEQUENCE] = 0xff;
@ -83,6 +98,11 @@ static int test_dtls_unprocessed(int testidx)
SSL_ERROR_NONE)))
goto end;
if (timer_cb_count == 0) {
printf("timer_callback was not called.\n");
goto end;
}
testresult = 1;
end:
SSL_free(serverssl1);

View file

@ -469,3 +469,4 @@ SSL_SESSION_set_max_early_data 469 1_1_1 EXIST::FUNCTION:
SSL_SESSION_set1_alpn_selected 470 1_1_1 EXIST::FUNCTION:
SSL_SESSION_set1_hostname 471 1_1_1 EXIST::FUNCTION:
SSL_SESSION_get0_alpn_selected 472 1_1_1 EXIST::FUNCTION:
DTLS_set_timer_cb 473 1_1_1 EXIST::FUNCTION:

View file

@ -18,6 +18,7 @@ BIO_lookup_type datatype
CRYPTO_EX_dup datatype
CRYPTO_EX_free datatype
CRYPTO_EX_new datatype
DTLS_timer_cb datatype
EVP_PKEY_gen_cb datatype
EVP_PKEY_METHOD datatype
GEN_SESSION_CB datatype