Keep the DTLS timer running after the end of the handshake if appropriate
authorMatt Caswell <matt@openssl.org>
Thu, 3 May 2018 15:00:51 +0000 (16:00 +0100)
committerMatt Caswell <matt@openssl.org>
Fri, 11 May 2018 12:54:56 +0000 (13:54 +0100)
During a full handshake the server is the last one to "speak". The timer
should continue to run until we know that the client has received our last
flight (e.g. because we receive some application data).

Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/6196)

ssl/record/rec_layer_d1.c
ssl/statem/statem_lib.c

index 083dac4339fa6b45308a8b7dae68d6d6f796e70c..0eeed4fc10073a24d4112c868d7c54beed46c451 100644 (file)
@@ -444,6 +444,19 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
             && SSL3_RECORD_get_length(rr) != 0)
         s->rlayer.alert_count = 0;
 
+    if (SSL3_RECORD_get_type(rr) != SSL3_RT_HANDSHAKE
+            && SSL3_RECORD_get_type(rr) != SSL3_RT_CHANGE_CIPHER_SPEC
+            && !SSL_in_init(s)
+            && (s->d1->next_timeout.tv_sec != 0
+                || s->d1->next_timeout.tv_usec != 0)) {
+        /*
+         * The timer is still running but we've received something that isn't
+         * handshake data - so the peer must have finished processing our
+         * last handshake flight. Stop the timer.
+         */
+        dtls1_stop_timer(s);
+    }
+
     /* we now have a packet which can be read and processed */
 
     if (s->s3->change_cipher_spec /* set when we receive ChangeCipherSpec,
index c4d4f26f7ef7e403d1616f6c4d888a80621cdc2c..eba4c6fb40118b1994e4a869bd10d516fa15b231 100644 (file)
@@ -299,6 +299,15 @@ WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst)
 
             s->ctx->stats.sess_accept_good++;
             s->handshake_func = ossl_statem_accept;
+
+            if (SSL_IS_DTLS(s) && !s->hit) {
+                /*
+                 * We are finishing after the client. We start the timer going
+                 * in case there are any retransmits of our final flight
+                 * required.
+                 */
+                dtls1_start_timer(s);
+            }
         } else {
             ssl_update_cache(s, SSL_SESS_CACHE_CLIENT);
             if (s->hit)
@@ -306,6 +315,15 @@ WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst)
 
             s->handshake_func = ossl_statem_connect;
             s->ctx->stats.sess_connect_good++;
+
+            if (SSL_IS_DTLS(s) && s->hit) {
+                /*
+                 * We are finishing after the server. We start the timer going
+                 * in case there are any retransmits of our final flight
+                 * required.
+                 */
+                dtls1_start_timer(s);
+            }
         }
 
         if (s->info_callback != NULL)