[openssl-commits] [openssl] master update

Matt Caswell matt at openssl.org
Tue May 8 08:44:38 UTC 2018


The branch master has been updated
       via  61e96557f9eae0258074c9cec7ad6aa1b9dde1df (commit)
       via  f7506416b1311e65d5c440defdbcfe176f633c50 (commit)
       via  ad962252857aac4350139fdbb6c8e3e6b0bdad7b (commit)
       via  6f6da2fe1710842c37c73ed2b114cf6942221db6 (commit)
       via  f20404fce90919b614b737d07cc75d9e1c019fb8 (commit)
      from  e15e92dbd5248bc8dbd95d2c0af33a6daf8f7255 (commit)


- Log -----------------------------------------------------------------
commit 61e96557f9eae0258074c9cec7ad6aa1b9dde1df
Author: Matt Caswell <matt at openssl.org>
Date:   Thu May 3 12:06:38 2018 +0100

    Add a DTLS test for dropped records
    
    Drop a record from a handshake and check that we can still complete the
    handshake. Repeat for all records in the handshake.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/6170)

commit f7506416b1311e65d5c440defdbcfe176f633c50
Author: Matt Caswell <matt at openssl.org>
Date:   Thu May 3 16:00:51 2018 +0100

    Keep the DTLS timer running after the end of the handshake if appropriate
    
    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 at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/6170)

commit ad962252857aac4350139fdbb6c8e3e6b0bdad7b
Author: Matt Caswell <matt at openssl.org>
Date:   Thu May 3 16:00:05 2018 +0100

    Only auto-retry for DTLS if configured to do so
    
    Otherwise we may end up in a hang when using blocking sockets
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/6170)

commit 6f6da2fe1710842c37c73ed2b114cf6942221db6
Author: Matt Caswell <matt at openssl.org>
Date:   Thu May 3 15:59:31 2018 +0100

    Fix s_client and s_server so that they correctly handle the DTLS timer
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/6170)

commit f20404fce90919b614b737d07cc75d9e1c019fb8
Author: Matt Caswell <matt at openssl.org>
Date:   Thu May 3 12:07:47 2018 +0100

    Don't fail on an out-of-order CCS in DTLS
    
    Fixes #4929
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/6170)

-----------------------------------------------------------------------

Summary of changes:
 apps/s_client.c           |   7 +--
 apps/s_server.c           |   7 +--
 ssl/record/rec_layer_d1.c |  25 ++++++++++
 ssl/statem/statem.c       |   4 +-
 ssl/statem/statem_clnt.c  |  14 ++++++
 ssl/statem/statem_lib.c   |  18 +++++++
 ssl/statem/statem_srvr.c  |  14 ++++++
 test/dtlstest.c           | 121 +++++++++++++++++++++++++++++++++++++++++++++-
 test/ssltestlib.c         |  83 ++++++++++++++++++++++++++++---
 test/ssltestlib.h         |   8 +++
 10 files changed, 281 insertions(+), 20 deletions(-)

diff --git a/apps/s_client.c b/apps/s_client.c
index 9d463f6..96f9da6 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -2703,8 +2703,7 @@ int s_client_main(int argc, char **argv)
         FD_ZERO(&readfds);
         FD_ZERO(&writefds);
 
-        if ((SSL_version(con) == DTLS1_VERSION) &&
-            DTLSv1_get_timeout(con, &timeout))
+        if (SSL_is_dtls(con) && DTLSv1_get_timeout(con, &timeout))
             timeoutp = &timeout;
         else
             timeoutp = NULL;
@@ -2815,10 +2814,8 @@ int s_client_main(int argc, char **argv)
             }
         }
 
-        if ((SSL_version(con) == DTLS1_VERSION)
-            && DTLSv1_handle_timeout(con) > 0) {
+        if (SSL_is_dtls(con) && DTLSv1_handle_timeout(con) > 0)
             BIO_printf(bio_err, "TIMEOUT occurred\n");
-        }
 
         if (!ssl_pending && FD_ISSET(SSL_get_fd(con), &writefds)) {
             k = SSL_write(con, &(cbuf[cbuf_off]), (unsigned int)cbuf_len);
diff --git a/apps/s_server.c b/apps/s_server.c
index ef39a4f..b0e9659 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -2398,18 +2398,15 @@ static int sv_body(int s, int stype, int prot, unsigned char *context)
             if ((i < 0) || (!i && !read_from_terminal))
                 continue;
 #else
-            if ((SSL_version(con) == DTLS1_VERSION) &&
-                DTLSv1_get_timeout(con, &timeout))
+            if (SSL_is_dtls(con) && DTLSv1_get_timeout(con, &timeout))
                 timeoutp = &timeout;
             else
                 timeoutp = NULL;
 
             i = select(width, (void *)&readfds, NULL, NULL, timeoutp);
 
-            if ((SSL_version(con) == DTLS1_VERSION)
-                && DTLSv1_handle_timeout(con) > 0) {
+            if ((SSL_is_dtls(con)) && DTLSv1_handle_timeout(con) > 0)
                 BIO_printf(bio_err, "TIMEOUT occurred\n");
-            }
 
             if (i <= 0)
                 continue;
diff --git a/ssl/record/rec_layer_d1.c b/ssl/record/rec_layer_d1.c
index 97943d4..37a2eb1 100644
--- a/ssl/record/rec_layer_d1.c
+++ b/ssl/record/rec_layer_d1.c
@@ -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,
@@ -664,6 +677,18 @@ int dtls1_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
                     return -1;
             }
             SSL3_RECORD_set_length(rr, 0);
+            if (!(s->mode & SSL_MODE_AUTO_RETRY)) {
+                if (SSL3_BUFFER_get_left(&s->rlayer.rbuf) == 0) {
+                    /* no read-ahead left? */
+                    BIO *bio;
+
+                    s->rwstate = SSL_READING;
+                    bio = SSL_get_rbio(s);
+                    BIO_clear_retry_flags(bio);
+                    BIO_set_retry_read(bio);
+                    return -1;
+                }
+            }
             goto start;
         }
 
diff --git a/ssl/statem/statem.c b/ssl/statem/statem.c
index 1f221e7..e836769 100644
--- a/ssl/statem/statem.c
+++ b/ssl/statem/statem.c
@@ -589,10 +589,8 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
              * Validate that we are allowed to move to the new state and move
              * to that state if so
              */
-            if (!transition(s, mt)) {
-                check_fatal(s, SSL_F_READ_STATE_MACHINE);
+            if (!transition(s, mt))
                 return SUB_STATE_ERROR;
-            }
 
             if (s->s3->tmp.message_size > max_message_size(s)) {
                 SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_READ_STATE_MACHINE,
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index 91b986f..60e987a 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -375,6 +375,20 @@ int ossl_statem_client_read_transition(SSL *s, int mt)
 
  err:
     /* No valid transition found */
+    if (SSL_IS_DTLS(s) && mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
+        BIO *rbio;
+
+        /*
+         * CCS messages don't have a message sequence number so this is probably
+         * because of an out-of-order CCS. We'll just drop it.
+         */
+        s->init_num = 0;
+        s->rwstate = SSL_READING;
+        rbio = SSL_get_rbio(s);
+        BIO_clear_retry_flags(rbio);
+        BIO_set_retry_read(rbio);
+        return 0;
+    }
     SSLfatal(s, SSL3_AD_UNEXPECTED_MESSAGE,
              SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION,
              SSL_R_UNEXPECTED_MESSAGE);
diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c
index 49b4443..74ad6e8 100644
--- a/ssl/statem/statem_lib.c
+++ b/ssl/statem/statem_lib.c
@@ -1057,6 +1057,15 @@ WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs, int stop)
             CRYPTO_atomic_add(&s->ctx->stats.sess_accept_good, 1, &discard,
                               s->ctx->lock);
             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 {
             /*
              * In TLSv1.3 we update the cache as part of processing the
@@ -1071,6 +1080,15 @@ WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs, int stop)
             s->handshake_func = ossl_statem_connect;
             CRYPTO_atomic_add(&s->session_ctx->stats.sess_connect_good, 1,
                               &discard, s->session_ctx->lock);
+
+            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 (SSL_IS_DTLS(s)) {
diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c
index aa38fad..018daaa 100644
--- a/ssl/statem/statem_srvr.c
+++ b/ssl/statem/statem_srvr.c
@@ -277,6 +277,20 @@ int ossl_statem_server_read_transition(SSL *s, int mt)
 
  err:
     /* No valid transition found */
+    if (SSL_IS_DTLS(s) && mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
+        BIO *rbio;
+
+        /*
+         * CCS messages don't have a message sequence number so this is probably
+         * because of an out-of-order CCS. We'll just drop it.
+         */
+        s->init_num = 0;
+        s->rwstate = SSL_READING;
+        rbio = SSL_get_rbio(s);
+        BIO_clear_retry_flags(rbio);
+        BIO_set_retry_read(rbio);
+        return 0;
+    }
     SSLfatal(s, SSL3_AD_UNEXPECTED_MESSAGE,
              SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION,
              SSL_R_UNEXPECTED_MESSAGE);
diff --git a/test/dtlstest.c b/test/dtlstest.c
index 16d4e0f..859ec6b 100644
--- a/test/dtlstest.c
+++ b/test/dtlstest.c
@@ -46,7 +46,7 @@ static unsigned int timer_cb(SSL *s, unsigned int timer_us)
     ++timer_cb_count;
 
     if (timer_us == 0)
-        return 1000000;
+        return 50000;
     else
         return 2 * timer_us;
 }
@@ -114,6 +114,123 @@ static int test_dtls_unprocessed(int testidx)
     return testresult;
 }
 
+#define CLI_TO_SRV_EPOCH_0_RECS 3
+#define CLI_TO_SRV_EPOCH_1_RECS 1
+#define SRV_TO_CLI_EPOCH_0_RECS 12
+#define SRV_TO_CLI_EPOCH_1_RECS 1
+#define TOTAL_FULL_HAND_RECORDS \
+            (CLI_TO_SRV_EPOCH_0_RECS + CLI_TO_SRV_EPOCH_1_RECS + \
+             SRV_TO_CLI_EPOCH_0_RECS + SRV_TO_CLI_EPOCH_1_RECS)
+
+#define CLI_TO_SRV_RESUME_EPOCH_0_RECS 3
+#define CLI_TO_SRV_RESUME_EPOCH_1_RECS 1
+#define SRV_TO_CLI_RESUME_EPOCH_0_RECS 2
+#define SRV_TO_CLI_RESUME_EPOCH_1_RECS 1
+#define TOTAL_RESUME_HAND_RECORDS \
+            (CLI_TO_SRV_RESUME_EPOCH_0_RECS + CLI_TO_SRV_RESUME_EPOCH_1_RECS + \
+             SRV_TO_CLI_RESUME_EPOCH_0_RECS + SRV_TO_CLI_RESUME_EPOCH_1_RECS)
+
+#define TOTAL_RECORDS (TOTAL_FULL_HAND_RECORDS + TOTAL_RESUME_HAND_RECORDS)
+
+static int test_dtls_drop_records(int idx)
+{
+    SSL_CTX *sctx = NULL, *cctx = NULL;
+    SSL *serverssl = NULL, *clientssl = NULL;
+    BIO *c_to_s_fbio, *mempackbio;
+    int testresult = 0;
+    int epoch = 0;
+    SSL_SESSION *sess = NULL;
+    int cli_to_srv_epoch0, cli_to_srv_epoch1, srv_to_cli_epoch0;
+
+    if (!TEST_true(create_ssl_ctx_pair(DTLS_server_method(),
+                                       DTLS_client_method(),
+                                       DTLS1_VERSION, DTLS_MAX_VERSION,
+                                       &sctx, &cctx, cert, privkey)))
+        return 0;
+
+    if (idx >= TOTAL_FULL_HAND_RECORDS) {
+        /* We're going to do a resumption handshake. Get a session first. */
+        if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
+                                          NULL, NULL))
+                || !TEST_true(create_ssl_connection(serverssl, clientssl,
+                              SSL_ERROR_NONE))
+                || !TEST_ptr(sess = SSL_get1_session(clientssl)))
+            goto end;
+
+        SSL_shutdown(clientssl);
+        SSL_shutdown(serverssl);
+        SSL_free(serverssl);
+        SSL_free(clientssl);
+        serverssl = clientssl = NULL;
+
+        cli_to_srv_epoch0 = CLI_TO_SRV_RESUME_EPOCH_0_RECS;
+        cli_to_srv_epoch1 = CLI_TO_SRV_RESUME_EPOCH_1_RECS;
+        srv_to_cli_epoch0 = SRV_TO_CLI_RESUME_EPOCH_0_RECS;
+        idx -= TOTAL_FULL_HAND_RECORDS;
+    } else {
+        cli_to_srv_epoch0 = CLI_TO_SRV_EPOCH_0_RECS;
+        cli_to_srv_epoch1 = CLI_TO_SRV_EPOCH_1_RECS;
+        srv_to_cli_epoch0 = SRV_TO_CLI_EPOCH_0_RECS;
+    }
+
+    c_to_s_fbio = BIO_new(bio_f_tls_dump_filter());
+    if (!TEST_ptr(c_to_s_fbio))
+        goto end;
+
+    /* BIO is freed by create_ssl_connection on error */
+    if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
+                                      NULL, c_to_s_fbio)))
+        goto end;
+
+    if (sess != NULL) {
+        if (!TEST_true(SSL_set_session(clientssl, sess)))
+            goto end;
+    }
+
+    DTLS_set_timer_cb(clientssl, timer_cb);
+    DTLS_set_timer_cb(serverssl, timer_cb);
+
+    /* Work out which record to drop based on the test number */
+    if (idx >= cli_to_srv_epoch0 + cli_to_srv_epoch1) {
+        mempackbio = SSL_get_wbio(serverssl);
+        idx -= cli_to_srv_epoch0 + cli_to_srv_epoch1;
+        if (idx >= srv_to_cli_epoch0) {
+            epoch = 1;
+            idx -= srv_to_cli_epoch0;
+        }
+    } else {
+        mempackbio = SSL_get_wbio(clientssl);
+        if (idx >= cli_to_srv_epoch0) {
+            epoch = 1;
+            idx -= cli_to_srv_epoch0;
+        }
+         mempackbio = BIO_next(mempackbio);
+    }
+    BIO_ctrl(mempackbio, MEMPACKET_CTRL_SET_DROP_EPOCH, epoch, NULL);
+    BIO_ctrl(mempackbio, MEMPACKET_CTRL_SET_DROP_REC, idx, NULL);
+
+    if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
+        goto end;
+
+    if (sess != NULL && !TEST_true(SSL_session_reused(clientssl)))
+        goto end;
+
+    /* If the test did what we planned then it should have dropped a record */
+    if (!TEST_int_eq((int)BIO_ctrl(mempackbio, MEMPACKET_CTRL_GET_DROP_REC, 0,
+                                   NULL), -1))
+        goto end;
+
+    testresult = 1;
+ end:
+    SSL_SESSION_free(sess);
+    SSL_free(serverssl);
+    SSL_free(clientssl);
+    SSL_CTX_free(sctx);
+    SSL_CTX_free(cctx);
+
+    return testresult;
+}
+
 int setup_tests(void)
 {
     if (!TEST_ptr(cert = test_get_argument(0))
@@ -121,6 +238,8 @@ int setup_tests(void)
         return 0;
 
     ADD_ALL_TESTS(test_dtls_unprocessed, NUM_TESTS);
+    ADD_ALL_TESTS(test_dtls_drop_records, TOTAL_RECORDS);
+
     return 1;
 }
 
diff --git a/test/ssltestlib.c b/test/ssltestlib.c
index 959e329..041ae26 100644
--- a/test/ssltestlib.c
+++ b/test/ssltestlib.c
@@ -12,6 +12,34 @@
 #include "internal/nelem.h"
 #include "ssltestlib.h"
 #include "testutil.h"
+#include "e_os.h"
+
+#ifdef OPENSSL_SYS_UNIX
+# include <unistd.h>
+
+static ossl_inline void ossl_sleep(unsigned int millis) {
+    usleep(millis * 1000);
+}
+#elif defined(_WIN32)
+# include <windows.h>
+
+static ossl_inline void ossl_sleep(unsigned int millis) {
+    Sleep(millis);
+}
+#else
+/* Fallback to a busy wait */
+static ossl_inline void ossl_sleep(unsigned int millis) {
+    struct timeval start, now;
+    unsigned int elapsedms;
+
+    gettimeofday(&start, NULL);
+    do {
+        gettimeofday(&now, NULL);
+        elapsedms = (((now.tv_sec - start.tv_sec) * 1000000)
+                     + now.tv_usec - start.tv_usec) / 1000;
+    } while (elapsedms < millis);
+}
+#endif
 
 static int tls_dump_new(BIO *bi);
 static int tls_dump_free(BIO *a);
@@ -252,7 +280,10 @@ typedef struct mempacket_test_ctx_st {
     unsigned int currrec;
     unsigned int currpkt;
     unsigned int lastpkt;
+    unsigned int injected;
     unsigned int noinject;
+    unsigned int dropepoch;
+    int droprec;
 } MEMPACKET_TEST_CTX;
 
 static int mempacket_test_new(BIO *bi);
@@ -295,6 +326,8 @@ static int mempacket_test_new(BIO *bio)
         OPENSSL_free(ctx);
         return 0;
     }
+    ctx->dropepoch = 0;
+    ctx->droprec = -1;
     BIO_set_init(bio, 1);
     BIO_set_data(bio, ctx);
     return 1;
@@ -312,8 +345,8 @@ static int mempacket_test_free(BIO *bio)
 }
 
 /* Record Header values */
-#define EPOCH_HI        4
-#define EPOCH_LO        5
+#define EPOCH_HI        3
+#define EPOCH_LO        4
 #define RECORD_SEQUENCE 10
 #define RECORD_LEN_HI   11
 #define RECORD_LEN_LO   12
@@ -341,15 +374,15 @@ static int mempacket_test_read(BIO *bio, char *out, int outl)
     if (outl > thispkt->len)
         outl = thispkt->len;
 
-    if (thispkt->type != INJECT_PACKET_IGNORE_REC_SEQ) {
+    if (thispkt->type != INJECT_PACKET_IGNORE_REC_SEQ
+            && (ctx->injected || ctx->droprec >= 0)) {
         /*
          * Overwrite the record sequence number. We strictly number them in
          * the order received. Since we are actually a reliable transport
          * we know that there won't be any re-ordering. We overwrite to deal
          * with any packets that have been injected
          */
-        for (rem = thispkt->len, rec = thispkt->data
-                ; rem > 0; rec += len, rem -= len) {
+        for (rem = thispkt->len, rec = thispkt->data; rem > 0; rem -= len) {
             if (rem < DTLS1_RT_HEADER_LENGTH)
                 return -1;
             epoch = (rec[EPOCH_HI] << 8) | rec[EPOCH_LO];
@@ -364,10 +397,23 @@ static int mempacket_test_read(BIO *bio, char *out, int outl)
                 seq >>= 8;
                 offset++;
             } while (seq > 0);
-            ctx->currrec++;
 
             len = ((rec[RECORD_LEN_HI] << 8) | rec[RECORD_LEN_LO])
                   + DTLS1_RT_HEADER_LENGTH;
+            if (rem < (int)len)
+                return -1;
+            if (ctx->droprec == (int)ctx->currrec && ctx->dropepoch == epoch) {
+                if (rem > (int)len)
+                    memmove(rec, rec + len, rem - len);
+                outl -= len;
+                ctx->droprec = -1;
+                if (outl == 0)
+                    BIO_set_retry_read(bio);
+            } else {
+                rec += len;
+            }
+
+            ctx->currrec++;
         }
     }
 
@@ -390,6 +436,7 @@ int mempacket_test_inject(BIO *bio, const char *in, int inl, int pktnum,
     if (pktnum >= 0) {
         if (ctx->noinject)
             return -1;
+        ctx->injected  = 1;
     } else {
         ctx->noinject = 1;
     }
@@ -488,6 +535,15 @@ static long mempacket_test_ctrl(BIO *bio, int cmd, long num, void *ptr)
     case BIO_CTRL_FLUSH:
         ret = 1;
         break;
+    case MEMPACKET_CTRL_SET_DROP_EPOCH:
+        ctx->dropepoch = (unsigned int)num;
+        break;
+    case MEMPACKET_CTRL_SET_DROP_REC:
+        ctx->droprec = (int)num;
+        break;
+    case MEMPACKET_CTRL_GET_DROP_REC:
+        ret = ctx->droprec;
+        break;
     case BIO_CTRL_RESET:
     case BIO_CTRL_DUP:
     case BIO_CTRL_PUSH:
@@ -627,6 +683,7 @@ int create_ssl_connection(SSL *serverssl, SSL *clientssl, int want)
     int clienterr = 0, servererr = 0;
     unsigned char buf;
     size_t readbytes;
+    int isdtls = SSL_is_dtls(serverssl);
 
     do {
         err = SSL_ERROR_WANT_WRITE;
@@ -658,10 +715,24 @@ int create_ssl_connection(SSL *serverssl, SSL *clientssl, int want)
             return 0;
         if (clienterr && servererr)
             return 0;
+        if (isdtls) {
+            if (rets > 0 && retc <= 0)
+                DTLSv1_handle_timeout(serverssl);
+            if (retc > 0 && rets <= 0)
+                DTLSv1_handle_timeout(clientssl);
+        }
         if (++abortctr == MAXLOOPS) {
             TEST_info("No progress made");
             return 0;
         }
+        if (isdtls && abortctr <= 50 && (abortctr % 10) == 0) {
+            /*
+             * It looks like we're just spinning. Pause for a short period to
+             * give the DTLS timer a chance to do something. We only do this for
+             * the first few times to prevent hangs.
+             */
+            ossl_sleep(50);
+        }
     } while (retc <=0 || rets <= 0);
 
     /*
diff --git a/test/ssltestlib.h b/test/ssltestlib.h
index 353699d..c96dff5 100644
--- a/test/ssltestlib.h
+++ b/test/ssltestlib.h
@@ -32,6 +32,14 @@ void bio_s_mempacket_test_free(void);
 #define INJECT_PACKET                   1
 #define INJECT_PACKET_IGNORE_REC_SEQ    2
 
+/*
+ * Mempacket BIO ctrls. We make them large enough to not clash with standard BIO
+ * ctrl codes.
+ */
+#define MEMPACKET_CTRL_SET_DROP_EPOCH  (1 << 15)
+#define MEMPACKET_CTRL_SET_DROP_REC    (2 << 15)
+#define MEMPACKET_CTRL_GET_DROP_REC    (3 << 15)
+
 int mempacket_test_inject(BIO *bio, const char *in, int inl, int pktnum,
                           int type);
 


More information about the openssl-commits mailing list