Browse Source

Adding a method to change the initial DTLS retransmission timer value.

This allows an application to override the default of 1 second, which
is what's instructed in RFC 6347 but is not an absolute requirement.

Change-Id: I0bbb16e31990fbcab44a29325b6ec7757d5789e5
Reviewed-on: https://boringssl-review.googlesource.com/7930
Reviewed-by: David Benjamin <davidben@google.com>
kris/onging/CECPQ3_patch15
Taylor Brandstetter 8 years ago
committed by David Benjamin
parent
commit
376a0fed24
8 changed files with 85 additions and 9 deletions
  1. +14
    -0
      include/openssl/ssl.h
  2. +16
    -7
      ssl/d1_lib.c
  3. +2
    -2
      ssl/internal.h
  4. +4
    -0
      ssl/ssl_lib.c
  5. +4
    -0
      ssl/test/bssl_shim.cc
  6. +43
    -0
      ssl/test/runner/runner.go
  7. +1
    -0
      ssl/test/test_config.cc
  8. +1
    -0
      ssl/test/test_config.h

+ 14
- 0
include/openssl/ssl.h View File

@@ -487,6 +487,16 @@ OPENSSL_EXPORT int SSL_get_error(const SSL *ssl, int ret_code);
* and zero on failure. */
OPENSSL_EXPORT int SSL_set_mtu(SSL *ssl, unsigned mtu);

/* DTLSv1_set_initial_timeout_duration sets the initial duration for a DTLS
* handshake timeout.
*
* This duration overrides the default of 1 second, which is the strong
* recommendation of RFC 6347 (see section 4.2.4.1). However, there may exist
* situations where a shorter timeout would be beneficial, such as for
* time-sensitive applications. */
OPENSSL_EXPORT void DTLSv1_set_initial_timeout_duration(SSL *ssl,
unsigned duration_ms);

/* DTLSv1_get_timeout queries the next DTLS handshake timeout. If there is a
* timeout in progress, it sets |*out| to the time remaining and returns one.
* Otherwise, it returns zero.
@@ -3882,6 +3892,10 @@ struct ssl_st {
struct ssl3_state_st *s3; /* SSLv3 variables */
struct dtls1_state_st *d1; /* DTLSv1 variables */

/* initial_timeout_duration_ms is the default DTLS timeout duration in
* milliseconds. It's used to initialize the timer any time it's restarted. */
unsigned initial_timeout_duration_ms;

/* callback that allows applications to peek at protocol messages */
void (*msg_callback)(int write_p, int version, int content_type,
const void *buf, size_t len, SSL *ssl, void *arg);


+ 16
- 7
ssl/d1_lib.c View File

@@ -157,17 +157,26 @@ int dtls1_supports_cipher(const SSL_CIPHER *cipher) {
return cipher->algorithm_enc != SSL_RC4 && cipher->algorithm_enc != SSL_eNULL;
}

void DTLSv1_set_initial_timeout_duration(SSL *ssl, unsigned int duration_ms) {
ssl->initial_timeout_duration_ms = duration_ms;
}

void dtls1_start_timer(SSL *ssl) {
/* If timer is not set, initialize duration with 1 second */
/* If timer is not set, initialize duration (by default, 1 second) */
if (ssl->d1->next_timeout.tv_sec == 0 && ssl->d1->next_timeout.tv_usec == 0) {
ssl->d1->timeout_duration = 1;
ssl->d1->timeout_duration_ms = ssl->initial_timeout_duration_ms;
}

/* Set timeout to current time */
get_current_time(ssl, &ssl->d1->next_timeout);

/* Add duration to current time */
ssl->d1->next_timeout.tv_sec += ssl->d1->timeout_duration;
ssl->d1->next_timeout.tv_sec += ssl->d1->timeout_duration_ms / 1000;
ssl->d1->next_timeout.tv_usec += (ssl->d1->timeout_duration_ms % 1000) * 1000;
if (ssl->d1->next_timeout.tv_usec >= 1000000) {
ssl->d1->next_timeout.tv_sec++;
ssl->d1->next_timeout.tv_usec -= 1000000;
}
BIO_ctrl(SSL_get_rbio(ssl), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
&ssl->d1->next_timeout);
}
@@ -230,9 +239,9 @@ int dtls1_is_timer_expired(SSL *ssl) {
}

void dtls1_double_timeout(SSL *ssl) {
ssl->d1->timeout_duration *= 2;
if (ssl->d1->timeout_duration > 60) {
ssl->d1->timeout_duration = 60;
ssl->d1->timeout_duration_ms *= 2;
if (ssl->d1->timeout_duration_ms > 60000) {
ssl->d1->timeout_duration_ms = 60000;
}
dtls1_start_timer(ssl);
}
@@ -241,7 +250,7 @@ void dtls1_stop_timer(SSL *ssl) {
/* Reset everything */
ssl->d1->num_timeouts = 0;
memset(&ssl->d1->next_timeout, 0, sizeof(struct timeval));
ssl->d1->timeout_duration = 1;
ssl->d1->timeout_duration_ms = ssl->initial_timeout_duration_ms;
BIO_ctrl(SSL_get_rbio(ssl), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
&ssl->d1->next_timeout);
/* Clear retransmission buffer */


+ 2
- 2
ssl/internal.h View File

@@ -956,8 +956,8 @@ typedef struct dtls1_state_st {
* timeout. */
struct timeval next_timeout;

/* Timeout duration */
unsigned short timeout_duration;
/* timeout_duration_ms is the timeout duration in milliseconds. */
unsigned timeout_duration_ms;
} DTLS1_STATE;

extern const SSL3_ENC_METHOD TLSv1_enc_data;


+ 4
- 0
ssl/ssl_lib.c View File

@@ -369,6 +369,10 @@ SSL *SSL_new(SSL_CTX *ctx) {
ssl->min_version = ctx->min_version;
ssl->max_version = ctx->max_version;

/* RFC 6347 states that implementations SHOULD use an initial timer value of
* 1 second. */
ssl->initial_timeout_duration_ms = 1000;

ssl->options = ctx->options;
ssl->mode = ctx->mode;
ssl->max_cert_list = ctx->max_cert_list;


+ 4
- 0
ssl/test/bssl_shim.cc View File

@@ -1317,6 +1317,10 @@ static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx,
return false;
}
}
if (config->initial_timeout_duration_ms > 0) {
DTLSv1_set_initial_timeout_duration(ssl.get(),
config->initial_timeout_duration_ms);
}

int sock = Connect(config->port);
if (sock == -1) {


+ 43
- 0
ssl/test/runner/runner.go View File

@@ -4583,6 +4583,24 @@ var timeouts = []time.Duration{
60 * time.Second,
}

// shortTimeouts is an alternate set of timeouts which would occur if the
// initial timeout duration was set to 250ms.
var shortTimeouts = []time.Duration{
250 * time.Millisecond,
500 * time.Millisecond,
1 * time.Second,
2 * time.Second,
4 * time.Second,
8 * time.Second,
16 * time.Second,
32 * time.Second,
60 * time.Second,
60 * time.Second,
60 * time.Second,
60 * time.Second,
60 * time.Second,
}

func addDTLSRetransmitTests() {
// Test that this is indeed the timeout schedule. Stress all
// four patterns of handshake.
@@ -4659,6 +4677,31 @@ func addDTLSRetransmitTests() {
},
flags: []string{"-async"},
})

// Test the timeout schedule when a shorter initial timeout duration is set.
testCases = append(testCases, testCase{
protocol: dtls,
name: "DTLS-Retransmit-Short-Client",
config: Config{
Bugs: ProtocolBugs{
TimeoutSchedule: shortTimeouts[:len(shortTimeouts)-1],
},
},
resumeSession: true,
flags: []string{"-async", "-initial-timeout-duration-ms", "250"},
})
testCases = append(testCases, testCase{
protocol: dtls,
testType: serverTest,
name: "DTLS-Retransmit-Short-Server",
config: Config{
Bugs: ProtocolBugs{
TimeoutSchedule: shortTimeouts[:len(shortTimeouts)-1],
},
},
resumeSession: true,
flags: []string{"-async", "-initial-timeout-duration-ms", "250"},
})
}

func addExportKeyingMaterialTests() {


+ 1
- 0
ssl/test/test_config.cc View File

@@ -148,6 +148,7 @@ const Flag<int> kIntFlags[] = {
&TestConfig::expect_server_key_exchange_hash },
{ "-expect-key-exchange-info",
&TestConfig::expect_key_exchange_info },
{ "-initial-timeout-duration-ms", &TestConfig::initial_timeout_duration_ms },
};

} // namespace


+ 1
- 0
ssl/test/test_config.h View File

@@ -104,6 +104,7 @@ struct TestConfig {
bool use_sparse_dh_prime = false;
int expect_key_exchange_info = 0;
bool use_old_client_cert_callback = false;
int initial_timeout_duration_ms = 0;
};

bool ParseConfig(int argc, char **argv, TestConfig *out_config);


Loading…
Cancel
Save