[openssl-commits] [openssl] master update

Matt Caswell matt at openssl.org
Thu Aug 4 20:01:23 UTC 2016


The branch master has been updated
       via  16938284cf5bba32006925281cb28b04d166a234 (commit)
       via  2e94723c1b5d8ab974645e83de90b248265af3cd (commit)
       via  032924c4b4104654ff8659b4701e4ab25872a12e (commit)
       via  387cf21345f981d3897f88a6479d8e60721c2c6b (commit)
       via  ff4952896ec4383a107bbe94001ca0a64ff47433 (commit)
       via  e6027420b7124d6196ccff391063a6626b1fab62 (commit)
       via  c8a18468caef4d62778381be0acdadc8a88d6e51 (commit)
      from  715d69b0d5fb5b873a923fc3f5c7b441ad73003c (commit)


- Log -----------------------------------------------------------------
commit 16938284cf5bba32006925281cb28b04d166a234
Author: David Woodhouse <David.Woodhouse at intel.com>
Date:   Mon Jul 25 14:31:43 2016 +0100

    Add basic test for Cisco DTLS1_BAD_VER and record replay handling
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit 2e94723c1b5d8ab974645e83de90b248265af3cd
Author: David Woodhouse <David.Woodhouse at intel.com>
Date:   Tue Aug 2 22:54:46 2016 +0100

    Fix ubsan 'left shift of negative value -1' error in satsub64be()
    
    Baroque, almost uncommented code triggers behaviour which is undefined
    by the C standard. You might quite reasonably not care that the code was
    broken on ones-complement machines, but if we support a ubsan build then
    we need to at least pretend to care.
    
    It looks like the special-case code for 64-bit big-endian is going to
    behave differently (and wrongly) on wrap-around, because it treats the
    values as signed. That seems wrong, and allows replay and other attacks.
    Surely you need to renegotiate and start a new epoch rather than
    wrapping around to sequence number zero again?
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit 032924c4b4104654ff8659b4701e4ab25872a12e
Author: David Woodhouse <David.Woodhouse at intel.com>
Date:   Mon Jul 25 18:03:27 2016 +0100

    Make DTLS1_BAD_VER work with DTLS_client_method()
    
    DTLSv1_client_method() is deprecated, but it was the only way to obtain
    DTLS1_BAD_VER support. The SSL_OP_CISCO_ANYCONNECT hack doesn't work with
    DTLS_client_method(), and it's relatively non-trivial to make it work without
    expanding the hack into lots of places.
    
    So deprecate SSL_OP_CISCO_ANYCONNECT with DTLSv1_client_method(), and make
    it work with SSL_CTX_set_{min,max}_proto_version(DTLS1_BAD_VER) instead.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit 387cf21345f981d3897f88a6479d8e60721c2c6b
Author: David Woodhouse <David.Woodhouse at intel.com>
Date:   Fri Jul 8 20:59:50 2016 +0100

    Fix cipher support for DTLS1_BAD_VER
    
    Commit 3eb2aff40 ("Add support for minimum and maximum protocol version
    supported by a cipher") disabled all ciphers for DTLS1_BAD_VER.
    
    That wasn't helpful. Give them back.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit ff4952896ec4383a107bbe94001ca0a64ff47433
Author: David Woodhouse <David.Woodhouse at intel.com>
Date:   Fri Jul 8 20:56:38 2016 +0100

    Fix DTLS_VERSION_xx() comparison macros for DTLS1_BAD_VER
    
    DTLS version numbers are strange and backwards, except DTLS1_BAD_VER so
    we have to make a special case for it.
    
    This does leave us with a set of macros which will evaluate their arguments
    more than once, but it's not a public-facing API and it's not like this is
    the kind of thing where people will be using DTLS_VERSION_LE(x++, y) anyway.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit e6027420b7124d6196ccff391063a6626b1fab62
Author: David Woodhouse <David.Woodhouse at intel.com>
Date:   Fri Jul 8 20:47:42 2016 +0100

    Fix ossl_statem_client_max_message_size() for DTLS1_BAD_VER
    
    The Change Cipher Spec message in this ancient pre-standard version of DTLS
    that Cisco are unfortunately still using in their products, is 3 bytes.
    
    Allow it.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit c8a18468caef4d62778381be0acdadc8a88d6e51
Author: David Woodhouse <David.Woodhouse at intel.com>
Date:   Fri Jul 8 20:46:07 2016 +0100

    Fix SSL_export_keying_material() for DTLS1_BAD_VER
    
    Commit d8e8590e ("Fix missing return value checks in SCTP") made the
    DTLS handshake fail, even for non-SCTP connections, if
    SSL_export_keying_material() fails. Which it does, for DTLS1_BAD_VER.
    
    Apply the trivial fix to make it succeed, since there's no real reason
    why it shouldn't even though we never need it.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    Reviewed-by: Matt Caswell <matt at openssl.org>

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

Summary of changes:
 include/openssl/ssl.h                              |   7 +-
 ssl/d1_lib.c                                       |   9 +-
 ssl/methods.c                                      |   5 +
 ssl/record/dtls1_bitmap.c                          |  61 +-
 ssl/record/rec_layer_d1.c                          |   3 +-
 ssl/s3_lib.c                                       | 176 +++---
 ssl/ssl_lib.c                                      |   2 +-
 ssl/ssl_locl.h                                     |  12 +-
 ssl/statem/statem_clnt.c                           |   2 +
 ssl/statem/statem_lib.c                            |   4 +-
 test/bad_dtls_test.c                               | 637 +++++++++++++++++++++
 test/build.info                                    |   6 +-
 .../{90-test_bioprint.t => 70-test_bad_dtls.t}     |  12 +-
 13 files changed, 814 insertions(+), 122 deletions(-)
 create mode 100644 test/bad_dtls_test.c
 copy test/recipes/{90-test_bioprint.t => 70-test_bad_dtls.t} (58%)

diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 2aca2f9..e58ad30 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -306,8 +306,11 @@ typedef int (*custom_ext_parse_cb) (SSL *s, unsigned int ext_type,
 # define SSL_OP_COOKIE_EXCHANGE              0x00002000U
 /* Don't use RFC4507 ticket extension */
 # define SSL_OP_NO_TICKET                    0x00004000U
-/* Use Cisco's "speshul" version of DTLS_BAD_VER (as client)  */
-# define SSL_OP_CISCO_ANYCONNECT             0x00008000U
+# ifndef OPENSSL_NO_DTLS1_METHOD
+/* Use Cisco's "speshul" version of DTLS_BAD_VER
+ * (only with deprecated DTLSv1_client_method())  */
+#  define SSL_OP_CISCO_ANYCONNECT             0x00008000U
+# endif
 
 /* As server, disallow session resumption on renegotiation */
 # define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION   0x00010000U
diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c
index 0a98555..08a5037 100644
--- a/ssl/d1_lib.c
+++ b/ssl/d1_lib.c
@@ -179,10 +179,13 @@ void dtls1_clear(SSL *s)
     }
 
     ssl3_clear(s);
-    if (s->options & SSL_OP_CISCO_ANYCONNECT)
-        s->client_version = s->version = DTLS1_BAD_VER;
-    else if (s->method->version == DTLS_ANY_VERSION)
+
+    if (s->method->version == DTLS_ANY_VERSION)
         s->version = DTLS_MAX_VERSION;
+#ifndef OPENSSL_NO_DTLS1_METHOD
+    else if (s->options & SSL_OP_CISCO_ANYCONNECT)
+        s->client_version = s->version = DTLS1_BAD_VER;
+#endif
     else
         s->version = s->method->version;
 }
diff --git a/ssl/methods.c b/ssl/methods.c
index aeed8c7..7d27f9d 100644
--- a/ssl/methods.c
+++ b/ssl/methods.c
@@ -191,6 +191,11 @@ IMPLEMENT_dtls1_meth_func(DTLS1_VERSION, SSL_METHOD_NO_SUITEB, SSL_OP_NO_DTLSv1,
                           ssl_undefined_function,
                           ossl_statem_connect,
                           DTLSv1_enc_data)
+IMPLEMENT_dtls1_meth_func(DTLS1_BAD_VER, SSL_METHOD_NO_SUITEB, SSL_OP_NO_DTLSv1,
+                          dtls_bad_ver_client_method,
+                          ssl_undefined_function,
+                          ossl_statem_connect,
+                          DTLSv1_enc_data)
 #endif
 
 #ifndef OPENSSL_NO_DTLS1_2_METHOD
diff --git a/ssl/record/dtls1_bitmap.c b/ssl/record/dtls1_bitmap.c
index 9dae9b2..ecc715d 100644
--- a/ssl/record/dtls1_bitmap.c
+++ b/ssl/record/dtls1_bitmap.c
@@ -13,7 +13,7 @@
 /* mod 128 saturating subtract of two 64-bit values in big-endian order */
 static int satsub64be(const unsigned char *v1, const unsigned char *v2)
 {
-    int ret, sat, brw, i;
+    int ret, i;
 
     if (sizeof(long) == 8)
         do {
@@ -45,28 +45,51 @@ static int satsub64be(const unsigned char *v1, const unsigned char *v2)
                 return (int)l;
         } while (0);
 
-    ret = (int)v1[7] - (int)v2[7];
-    sat = 0;
-    brw = ret >> 8;             /* brw is either 0 or -1 */
-    if (ret & 0x80) {
-        for (i = 6; i >= 0; i--) {
-            brw += (int)v1[i] - (int)v2[i];
-            sat |= ~brw;
-            brw >>= 8;
-        }
-    } else {
-        for (i = 6; i >= 0; i--) {
-            brw += (int)v1[i] - (int)v2[i];
-            sat |= brw;
-            brw >>= 8;
+    ret = 0;
+    for (i=0; i<7; i++) {
+        if (v1[i] > v2[i]) {
+            /* v1 is larger... but by how much? */
+            if (v1[i] != v2[i] + 1)
+                return 128;
+            while (++i <= 6) {
+                if (v1[i] != 0x00 || v2[i] != 0xff)
+                    return 128; /* too much */
+            }
+            /* We checked all the way to the penultimate byte,
+             * so despite higher bytes changing we actually
+             * know that it only changed from (e.g.)
+             *       ... (xx)  ff ff ff ??
+             * to   ... (xx+1) 00 00 00 ??
+             * so we add a 'bias' of 256 for the carry that
+             * happened, and will eventually return
+             * 256 + v1[7] - v2[7]. */
+            ret = 256;
+            break;
+        } else if (v2[i] > v1[i]) {
+            /* v2 is larger... but by how much? */
+            if (v2[i] != v1[i] + 1)
+                return -128;
+            while (++i <= 6) {
+                if (v2[i] != 0x00 || v1[i] != 0xff)
+                    return -128; /* too much */
+            }
+            /* Similar to the case above, we know it changed
+             * from    ... (xx)  00 00 00 ??
+             * to     ... (xx-1) ff ff ff ??
+             * so we add a 'bias' of -256 for the borrow,
+             * to return -256 + v1[7] - v2[7]. */
+            ret = -256;
         }
     }
-    brw <<= 8;                  /* brw is either 0 or -256 */
 
-    if (sat & 0xff)
-        return brw | 0x80;
+    ret += (int)v1[7] - (int)v2[7];
+
+    if (ret > 128)
+        return 128;
+    else if (ret < -128)
+        return -128;
     else
-        return brw + (ret & 0xFF);
+        return ret;
 }
 
 int dtls1_record_replay_check(SSL *s, DTLS1_BITMAP *bitmap)
diff --git a/ssl/record/rec_layer_d1.c b/ssl/record/rec_layer_d1.c
index cca5721..7ddadfa 100644
--- a/ssl/record/rec_layer_d1.c
+++ b/ssl/record/rec_layer_d1.c
@@ -980,7 +980,8 @@ int do_dtls1_write(SSL *s, int type, const unsigned char *buf,
      * haven't decided which version to use yet send back using version 1.0
      * header: otherwise some clients will ignore it.
      */
-    if (s->method->version == DTLS_ANY_VERSION) {
+    if (s->method->version == DTLS_ANY_VERSION &&
+	s->max_proto_version != DTLS1_BAD_VER) {
         *(p++) = DTLS1_VERSION >> 8;
         *(p++) = DTLS1_VERSION & 0xff;
     } else {
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 9158f21..e14b448 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -77,7 +77,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_eNULL,
      SSL_MD5,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_STRONG_NONE,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      0,
@@ -92,7 +92,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_eNULL,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_STRONG_NONE | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      0,
@@ -107,7 +107,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_3DES,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_MEDIUM | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      112,
@@ -122,7 +122,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_3DES,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      112,
@@ -137,7 +137,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_3DES,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_MEDIUM | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      112,
@@ -152,7 +152,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_3DES,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      112,
@@ -167,7 +167,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES128,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -182,7 +182,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES128,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -197,7 +197,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES128,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -212,7 +212,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES128,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -227,7 +227,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES256,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      256,
@@ -242,7 +242,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES256,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      256,
@@ -257,7 +257,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES256,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      256,
@@ -272,7 +272,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES256,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      256,
@@ -844,7 +844,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_eNULL,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_STRONG_NONE | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      0,
@@ -859,7 +859,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_3DES,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_MEDIUM | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      112,
@@ -874,7 +874,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES128,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -889,7 +889,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES256,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      256,
@@ -904,7 +904,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_eNULL,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_STRONG_NONE | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      0,
@@ -919,7 +919,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_3DES,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_MEDIUM | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      112,
@@ -934,7 +934,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES128,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -949,7 +949,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES256,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      256,
@@ -964,7 +964,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_eNULL,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_STRONG_NONE | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      0,
@@ -979,7 +979,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_3DES,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      112,
@@ -994,7 +994,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES128,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -1009,7 +1009,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES256,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      256,
@@ -1147,7 +1147,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_eNULL,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_STRONG_NONE | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      0,
@@ -1162,7 +1162,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_eNULL,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_STRONG_NONE | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      0,
@@ -1177,7 +1177,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_eNULL,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_STRONG_NONE | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      0,
@@ -1192,7 +1192,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_3DES,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_MEDIUM | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      112,
@@ -1207,7 +1207,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES128,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -1222,7 +1222,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES256,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      256,
@@ -1237,7 +1237,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_3DES,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_MEDIUM | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      112,
@@ -1252,7 +1252,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES128,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -1267,7 +1267,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES256,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      256,
@@ -1282,7 +1282,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_3DES,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_MEDIUM | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      112,
@@ -1297,7 +1297,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES128,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -1312,7 +1312,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES256,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      256,
@@ -1417,7 +1417,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES128,
      SSL_SHA256,
      TLS1_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -1432,7 +1432,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES256,
      SSL_SHA384,
      TLS1_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
      256,
@@ -1447,7 +1447,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_eNULL,
      SSL_SHA256,
      TLS1_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_STRONG_NONE | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      0,
@@ -1462,7 +1462,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_eNULL,
      SSL_SHA384,
      TLS1_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_STRONG_NONE | SSL_FIPS,
      SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
      0,
@@ -1477,7 +1477,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES128,
      SSL_SHA256,
      TLS1_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -1492,7 +1492,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES256,
      SSL_SHA384,
      TLS1_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
      256,
@@ -1507,7 +1507,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_eNULL,
      SSL_SHA256,
      TLS1_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_STRONG_NONE | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      0,
@@ -1522,7 +1522,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_eNULL,
      SSL_SHA384,
      TLS1_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_STRONG_NONE | SSL_FIPS,
      SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
      0,
@@ -1537,7 +1537,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES128,
      SSL_SHA256,
      TLS1_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -1552,7 +1552,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES256,
      SSL_SHA384,
      TLS1_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
      256,
@@ -1567,7 +1567,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_eNULL,
      SSL_SHA256,
      TLS1_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_STRONG_NONE | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      0,
@@ -1582,7 +1582,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_eNULL,
      SSL_SHA384,
      TLS1_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_STRONG_NONE | SSL_FIPS,
      SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
      0,
@@ -1598,7 +1598,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_3DES,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_MEDIUM | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      112,
@@ -1613,7 +1613,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES128,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -1628,7 +1628,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES256,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      256,
@@ -1643,7 +1643,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES128,
      SSL_SHA256,
      TLS1_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -1658,7 +1658,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES256,
      SSL_SHA384,
      TLS1_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH | SSL_FIPS,
      SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
      256,
@@ -1673,7 +1673,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_eNULL,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_STRONG_NONE | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      0,
@@ -1688,7 +1688,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_eNULL,
      SSL_SHA256,
      TLS1_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_STRONG_NONE | SSL_FIPS,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      0,
@@ -1703,7 +1703,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_eNULL,
      SSL_SHA384,
      TLS1_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_STRONG_NONE | SSL_FIPS,
      SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
      0,
@@ -1722,7 +1722,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_3DES,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_MEDIUM,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      112,
@@ -1737,7 +1737,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_3DES,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_MEDIUM,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      112,
@@ -1752,7 +1752,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_3DES,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_MEDIUM,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      112,
@@ -1767,7 +1767,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES128,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -1782,7 +1782,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES128,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -1797,7 +1797,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES128,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_HIGH,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -1812,7 +1812,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES256,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      256,
@@ -1827,7 +1827,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES256,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_HIGH,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      256,
@@ -1842,7 +1842,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_AES256,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_HIGH,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      256,
@@ -2096,7 +2096,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_CAMELLIA256,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_HIGH,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      256,
@@ -2111,7 +2111,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_CAMELLIA256,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_HIGH,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      256,
@@ -2126,7 +2126,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_CAMELLIA256,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_HIGH,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      256,
@@ -2141,7 +2141,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_CAMELLIA256,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_HIGH,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      256,
@@ -2156,7 +2156,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_CAMELLIA128,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_HIGH,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -2171,7 +2171,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_CAMELLIA128,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_HIGH,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -2186,7 +2186,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_CAMELLIA128,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_HIGH,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -2201,7 +2201,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_CAMELLIA128,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_HIGH,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -2281,7 +2281,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_CAMELLIA128,
      SSL_SHA256,
      TLS1_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_HIGH,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -2296,7 +2296,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_CAMELLIA256,
      SSL_SHA384,
      TLS1_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_HIGH,
      SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
      256,
@@ -2311,7 +2311,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_CAMELLIA128,
      SSL_SHA256,
      TLS1_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_HIGH,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -2326,7 +2326,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_CAMELLIA256,
      SSL_SHA384,
      TLS1_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_HIGH,
      SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
      256,
@@ -2341,7 +2341,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_CAMELLIA128,
      SSL_SHA256,
      TLS1_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_HIGH,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -2356,7 +2356,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_CAMELLIA256,
      SSL_SHA384,
      TLS1_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_HIGH,
      SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
      256,
@@ -2371,7 +2371,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_CAMELLIA128,
      SSL_SHA256,
      TLS1_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_HIGH,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -2386,7 +2386,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_CAMELLIA256,
      SSL_SHA384,
      TLS1_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_HIGH,
      SSL_HANDSHAKE_MAC_SHA384 | TLS1_PRF_SHA384,
      256,
@@ -2468,7 +2468,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_IDEA,
      SSL_SHA1,
      SSL3_VERSION, TLS1_1_VERSION,
-     DTLS1_VERSION, DTLS1_VERSION,
+     DTLS1_BAD_VER, DTLS1_VERSION,
      SSL_NOT_DEFAULT | SSL_MEDIUM,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -2486,7 +2486,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_SEED,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_MEDIUM,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -2501,7 +2501,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_SEED,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_MEDIUM,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -2516,7 +2516,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_SEED,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_MEDIUM,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
@@ -2531,7 +2531,7 @@ static SSL_CIPHER ssl3_ciphers[] =
      SSL_SEED,
      SSL_SHA1,
      SSL3_VERSION, TLS1_2_VERSION,
-     DTLS1_VERSION, DTLS1_2_VERSION,
+     DTLS1_BAD_VER, DTLS1_2_VERSION,
      SSL_NOT_DEFAULT | SSL_MEDIUM,
      SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
      128,
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index df71f7b..8c3c88e 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -2300,7 +2300,7 @@ int SSL_export_keying_material(SSL *s, unsigned char *out, size_t olen,
                                const unsigned char *p, size_t plen,
                                int use_context)
 {
-    if (s->version < TLS1_VERSION)
+    if (s->version < TLS1_VERSION && s->version != DTLS1_BAD_VER)
         return -1;
 
     return s->method->ssl3_enc->export_keying_material(s, out, olen, label,
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 25cd312..ef05f70 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -154,10 +154,13 @@
                            (c)[1]=(unsigned char)(((l)>> 8)&0xff), \
                            (c)[2]=(unsigned char)(((l)    )&0xff)),(c)+=3)
 
-#define DTLS_VERSION_GT(v1, v2) ((v1) < (v2))
-#define DTLS_VERSION_GE(v1, v2) ((v1) <= (v2))
-#define DTLS_VERSION_LT(v1, v2) ((v1) > (v2))
-#define DTLS_VERSION_LE(v1, v2) ((v1) >= (v2))
+/* DTLS version numbers are strange because they're inverted. Except
+ * for DTLS1_BAD_VER, which should be considered "lower" than the rest. */
+#define dtls_ver_ordinal(v1) (((v1) == DTLS1_BAD_VER) ? 0xff00 : (v1))
+#define DTLS_VERSION_GT(v1, v2) (dtls_ver_ordinal(v1) < dtls_ver_ordinal(v2))
+#define DTLS_VERSION_GE(v1, v2) (dtls_ver_ordinal(v1) <= dtls_ver_ordinal(v2))
+#define DTLS_VERSION_LT(v1, v2) (dtls_ver_ordinal(v1) > dtls_ver_ordinal(v2))
+#define DTLS_VERSION_LE(v1, v2) (dtls_ver_ordinal(v1) >= dtls_ver_ordinal(v2))
 
 /* LOCAL STUFF */
 
@@ -1652,6 +1655,7 @@ __owur const SSL_METHOD *tlsv1_2_client_method(void);
 __owur const SSL_METHOD *dtlsv1_method(void);
 __owur const SSL_METHOD *dtlsv1_server_method(void);
 __owur const SSL_METHOD *dtlsv1_client_method(void);
+__owur const SSL_METHOD *dtls_bad_ver_client_method(void);
 __owur const SSL_METHOD *dtlsv1_2_method(void);
 __owur const SSL_METHOD *dtlsv1_2_server_method(void);
 __owur const SSL_METHOD *dtlsv1_2_client_method(void);
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index 9d4af3a..df19211 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -589,6 +589,8 @@ unsigned long ossl_statem_client_max_message_size(SSL *s)
             return SERVER_HELLO_DONE_MAX_LENGTH;
 
         case TLS_ST_CR_CHANGE:
+            if (s->version == DTLS1_BAD_VER)
+                return 3;
             return CCS_MAX_LENGTH;
 
         case TLS_ST_CR_SESSION_TICKET:
diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c
index df07800..ae986f5 100644
--- a/ssl/statem/statem_lib.c
+++ b/ssl/statem/statem_lib.c
@@ -681,8 +681,10 @@ static const version_info dtls_version_table[] = {
 #endif
 #ifndef OPENSSL_NO_DTLS1
     { DTLS1_VERSION, dtlsv1_client_method, dtlsv1_server_method },
+    { DTLS1_BAD_VER, dtls_bad_ver_client_method, NULL },
 #else
     { DTLS1_VERSION, NULL, NULL },
+    { DTLS1_BAD_VER, NULL, NULL },
 #endif
     { 0, NULL, NULL },
 };
@@ -847,7 +849,7 @@ int ssl_set_version_bound(int method_version, int version, int *bound)
 
     case DTLS_ANY_VERSION:
         if (DTLS_VERSION_GT(version, DTLS_MAX_VERSION) ||
-            DTLS_VERSION_LT(version, DTLS1_VERSION))
+            DTLS_VERSION_LT(version, DTLS1_BAD_VER))
             return 0;
         break;
     }
diff --git a/test/bad_dtls_test.c b/test/bad_dtls_test.c
new file mode 100644
index 0000000..5d0c671
--- /dev/null
+++ b/test/bad_dtls_test.c
@@ -0,0 +1,637 @@
+/*
+ * Copyright 2016 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
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Unit test for Cisco DTLS1_BAD_VER session resume, as used by
+ * AnyConnect VPN protocol.
+ *
+ * This is designed to exercise the code paths in
+ * http://git.infradead.org/users/dwmw2/openconnect.git/blob/HEAD:/dtls.c
+ * which have frequently been affected by regressions in DTLS1_BAD_VER
+ * support.
+ *
+ * Note that unlike other SSL tests, we don't test against our own SSL
+ * server method. Firstly because we don't have one; we *only* support
+ * DTLS1_BAD_VER as a client. And secondly because even if that were
+ * fixed up it's the wrong thing to test against — because if changes
+ * are made in generic DTLS code which don't take DTLS1_BAD_VER into
+ * account, there's plenty of scope for making those changes such that
+ * they break *both* the client and the server in the same way.
+ *
+ * So we handle the server side manually. In a session resume there isn't
+ * much to be done anyway.
+ */
+#include <string.h>
+
+#include <openssl/opensslconf.h>
+#include <openssl/bio.h>
+#include <openssl/crypto.h>
+#include <openssl/evp.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <openssl/rand.h>
+#include <openssl/kdf.h>
+
+#include "ssl/packet_locl.h"
+#include "e_os.h" /* for OSSL_NELEM() */
+
+/* For DTLS1_BAD_VER packets the MAC doesn't include the handshake header */
+#define MAC_OFFSET (DTLS1_RT_HEADER_LENGTH + DTLS1_HM_HEADER_LENGTH)
+
+static unsigned char client_random[SSL3_RANDOM_SIZE];
+static unsigned char server_random[SSL3_RANDOM_SIZE];
+
+/* These are all generated locally, sized purely according to our own whim */
+static unsigned char session_id[32];
+static unsigned char master_secret[48];
+static unsigned char cookie[20];
+
+/* We've hard-coded the cipher suite; we know it's 104 bytes */
+static unsigned char key_block[104];
+#define mac_key (key_block + 20)
+#define dec_key (key_block + 40)
+#define enc_key (key_block + 56)
+
+static EVP_MD_CTX *handshake_md;
+
+static int do_PRF(const void *seed1, int seed1_len,
+                  const void *seed2, int seed2_len,
+                  const void *seed3, int seed3_len,
+                  unsigned char *out, int olen)
+{
+    EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_TLS1_PRF, NULL);
+    size_t outlen = olen;
+
+    /* No error handling. If it all screws up, the test will fail anyway */
+    EVP_PKEY_derive_init(pctx);
+    EVP_PKEY_CTX_set_tls1_prf_md(pctx, EVP_md5_sha1());
+    EVP_PKEY_CTX_set1_tls1_prf_secret(pctx, master_secret, sizeof(master_secret));
+    EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed1, seed1_len);
+    EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed2, seed2_len);
+    EVP_PKEY_CTX_add1_tls1_prf_seed(pctx, seed3, seed3_len);
+    EVP_PKEY_derive(pctx, out, &outlen);
+    EVP_PKEY_CTX_free(pctx);
+    return 1;
+}
+
+static SSL_SESSION *client_session(void)
+{
+    static unsigned char session_asn1[] = {
+        0x30, 0x5F,              /* SEQUENCE, length 0x5F */
+        0x02, 0x01, 0x01,        /* INTEGER, SSL_SESSION_ASN1_VERSION */
+        0x02, 0x02, 0x01, 0x00,  /* INTEGER, DTLS1_BAD_VER */
+        0x04, 0x02, 0x00, 0x2F,  /* OCTET_STRING, AES128-SHA */
+        0x04, 0x20,              /* OCTET_STRING, session id */
+#define SS_SESSID_OFS 15 /* Session ID goes here */
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x04, 0x30,              /* OCTET_STRING, master secret */
+#define SS_SECRET_OFS 49 /* Master secret goes here */
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    };
+    const unsigned char *p = session_asn1;
+
+    /* Copy the randomly-generated fields into the above ASN1 */
+    memcpy(session_asn1 + SS_SESSID_OFS, session_id, sizeof(session_id));
+    memcpy(session_asn1 + SS_SECRET_OFS, master_secret, sizeof(master_secret));
+
+    return d2i_SSL_SESSION(NULL, &p, sizeof(session_asn1));
+}
+
+/* PACKET_equal() doesn't quite do what we need. Provide a version that
+ * does, in a form that can easily be moved to ssl_locl.h if anyone else
+ * cares to come up with a better name and use it too... */
+__owur static ossl_inline int PACKET_starts(PACKET *pkt, const void *ptr,
+                                            size_t num)
+{
+    if (PACKET_remaining(pkt) < num)
+        return 0;
+    if (CRYPTO_memcmp(pkt->curr, ptr, num) != 0)
+        return 0;
+
+    packet_forward(pkt, num);
+    return 1;
+}
+
+/* Returns 1 for initial ClientHello, 2 for ClientHello with cookie */
+static int validate_client_hello(BIO *wbio)
+{
+    PACKET pkt;
+    long len;
+    unsigned char *data;
+    int cookie_found = 0;
+    unsigned int u;
+
+    len = BIO_get_mem_data(wbio, (char **)&data);
+    if (!PACKET_buf_init(&pkt, data, len))
+        return 0;
+
+    /* Check record header type */
+    if (!PACKET_get_1(&pkt, &u) || u != SSL3_RT_HANDSHAKE)
+        return 0;
+    /* Version */
+    if (!PACKET_get_net_2(&pkt, &u) || u != DTLS1_BAD_VER)
+        return 0;
+    /* Skip the rest of the record header */
+    if (!PACKET_forward(&pkt, DTLS1_RT_HEADER_LENGTH - 3))
+        return 0;
+
+    /* Check it's a ClientHello */
+    if (!PACKET_get_1(&pkt, &u) || u != SSL3_MT_CLIENT_HELLO)
+        return 0;
+    /* Skip the rest of the handshake message header */
+    if (!PACKET_forward(&pkt, DTLS1_HM_HEADER_LENGTH - 1))
+        return 0;
+
+    /* Check client version */
+    if (!PACKET_get_net_2(&pkt, &u) || u != DTLS1_BAD_VER)
+        return 0;
+
+    /* Store random */
+    if (!PACKET_copy_bytes(&pkt, client_random, SSL3_RANDOM_SIZE))
+        return 0;
+
+    /* Check session id length and content */
+    if (!PACKET_get_1(&pkt, &u))
+        return 0;
+    if (u != sizeof(session_id) || !PACKET_starts(&pkt, session_id, u))
+        return 0;
+
+    /* Check cookie */
+    if (!PACKET_get_1(&pkt, &u))
+        return 0;
+    if (u) {
+        if (u != sizeof(cookie) || !PACKET_starts(&pkt, cookie, u))
+            return 0;
+        cookie_found = 1;
+    }
+
+    /* Skip ciphers */
+    if (!PACKET_get_net_2(&pkt, &u) || !PACKET_forward(&pkt, u))
+        return 0;
+
+    /* Skip compression */
+    if (!PACKET_get_1(&pkt, &u) || !PACKET_forward(&pkt, u))
+        return 0;
+
+    /* Skip extensions */
+    if (!PACKET_get_net_2(&pkt, &u) || !PACKET_forward(&pkt, u))
+        return 0;
+
+    /* Now we are at the end */
+    if (PACKET_remaining(&pkt))
+        return 0;
+
+    /* Update handshake MAC for second ClientHello (with cookie) */
+    if (cookie_found && !EVP_DigestUpdate(handshake_md, data + MAC_OFFSET,
+                                          len - MAC_OFFSET))
+            printf("EVP_DigestUpdate() failed\n");
+
+    (void)BIO_reset(wbio);
+
+    return 1 + cookie_found;
+}
+
+static int send_hello_verify(BIO *rbio)
+{
+    static unsigned char hello_verify[] = {
+        0x16, /* Handshake */
+        0x01, 0x00, /* DTLS1_BAD_VER */
+        0x00, 0x00, /* Epoch 0 */
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Seq# 0 */
+        0x00, 0x23, /* Length */
+        0x03, /* Hello Verify */
+        0x00, 0x00, 0x17, /* Length */
+        0x00, 0x00, /* Seq# 0 */
+        0x00, 0x00, 0x00, /* Fragment offset */
+        0x00, 0x00, 0x17, /* Fragment length */
+        0x01, 0x00, /* DTLS1_BAD_VER */
+        0x14, /* Cookie length */
+#define HV_COOKIE_OFS 28 /* Cookie goes here */
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00,
+    };
+
+    memcpy(hello_verify + HV_COOKIE_OFS, cookie, sizeof(cookie));
+
+    BIO_write(rbio, hello_verify, sizeof(hello_verify));
+
+    return 1;
+}
+
+static int send_server_hello(BIO *rbio)
+{
+    static unsigned char server_hello[] = {
+        0x16, /* Handshake */
+        0x01, 0x00, /* DTLS1_BAD_VER */
+        0x00, 0x00, /* Epoch 0 */
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* Seq# 1 */
+        0x00, 0x52, /* Length */
+        0x02, /* Server Hello */
+        0x00, 0x00, 0x46, /* Length */
+        0x00, 0x01, /* Seq# */
+        0x00, 0x00, 0x00, /* Fragment offset */
+        0x00, 0x00, 0x46, /* Fragment length */
+        0x01, 0x00, /* DTLS1_BAD_VER */
+#define SH_RANDOM_OFS 27 /* Server random goes here */
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x20, /* Session ID length */
+#define SH_SESSID_OFS 60 /* Session ID goes here */
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x2f, /* Cipher suite AES128-SHA */
+        0x00, /* Compression null */
+    };
+    static unsigned char change_cipher_spec[] = {
+        0x14, /* Change Cipher Spec */
+        0x01, 0x00, /* DTLS1_BAD_VER */
+        0x00, 0x00, /* Epoch 0 */
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x02, /* Seq# 2 */
+        0x00, 0x03, /* Length */
+        0x01, 0x00, 0x02, /* Message */
+    };
+
+    memcpy(server_hello + SH_RANDOM_OFS, server_random, sizeof(server_random));
+    memcpy(server_hello + SH_SESSID_OFS, session_id, sizeof(session_id));
+
+    if (!EVP_DigestUpdate(handshake_md, server_hello + MAC_OFFSET,
+                          sizeof(server_hello) - MAC_OFFSET))
+        printf("EVP_DigestUpdate() failed\n");
+
+    BIO_write(rbio, server_hello, sizeof(server_hello));
+    BIO_write(rbio, change_cipher_spec, sizeof(change_cipher_spec));
+
+    return 1;
+}
+
+/* Create header, HMAC, pad, encrypt and send a record */
+static int send_record(BIO *rbio, unsigned char type, unsigned long seqnr,
+                       const void *msg, size_t len)
+{
+    /* Note that the order of the record header fields on the wire,
+     * and in the HMAC, is different. So we just keep them in separate
+     * variables and handle them individually. */
+    static unsigned char epoch[2] = { 0x00, 0x01 };
+    static unsigned char seq[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+    static unsigned char ver[2] = { 0x01, 0x00 }; /* DTLS1_BAD_VER */
+    unsigned char lenbytes[2];
+    HMAC_CTX *ctx;
+    EVP_CIPHER_CTX *enc_ctx;
+    unsigned char iv[16];
+    unsigned char pad;
+    unsigned char *enc;
+
+#ifdef SIXTY_FOUR_BIT_LONG
+    seq[0] = (seqnr >> 40) & 0xff;
+    seq[1] = (seqnr >> 32) & 0xff;
+#endif
+    seq[2] = (seqnr >> 24) & 0xff;
+    seq[3] = (seqnr >> 16) & 0xff;
+    seq[4] = (seqnr >> 8) & 0xff;
+    seq[5] = seqnr & 0xff;
+
+    pad = 15 - ((len + SHA_DIGEST_LENGTH) % 16);
+    enc = OPENSSL_malloc(len + SHA_DIGEST_LENGTH + 1 + pad);
+    if (enc == NULL)
+        return 0;
+
+    /* Copy record to encryption buffer */
+    memcpy(enc, msg, len);
+
+    /* Append HMAC to data */
+    ctx = HMAC_CTX_new();
+    HMAC_Init_ex(ctx, mac_key, 20, EVP_sha1(), NULL);
+    HMAC_Update(ctx, epoch, 2);
+    HMAC_Update(ctx, seq, 6);
+    HMAC_Update(ctx, &type, 1);
+    HMAC_Update(ctx, ver, 2); /* Version */
+    lenbytes[0] = len >> 8;
+    lenbytes[1] = len & 0xff;
+    HMAC_Update(ctx, lenbytes, 2); /* Length */
+    HMAC_Update(ctx, enc, len); /* Finally the data itself */
+    HMAC_Final(ctx, enc + len, NULL);
+    HMAC_CTX_free(ctx);
+
+    /* Append padding bytes */
+    len += SHA_DIGEST_LENGTH;
+    do {
+        enc[len++] = pad;
+    } while (len % 16);
+
+    /* Generate IV, and encrypt */
+    RAND_bytes(iv, sizeof(iv));
+    enc_ctx = EVP_CIPHER_CTX_new();
+    EVP_CipherInit_ex(enc_ctx, EVP_aes_128_cbc(), NULL, enc_key, iv, 1);
+    EVP_Cipher(enc_ctx, enc, enc, len);
+    EVP_CIPHER_CTX_free(enc_ctx);
+
+    /* Finally write header (from fragmented variables), IV and encrypted record */
+    BIO_write(rbio, &type, 1);
+    BIO_write(rbio, ver, 2);
+    BIO_write(rbio, epoch, 2);
+    BIO_write(rbio, seq, 6);
+    lenbytes[0] = (len + sizeof(iv)) >> 8;
+    lenbytes[1] = (len + sizeof(iv)) & 0xff;
+    BIO_write(rbio, lenbytes, 2);
+
+    BIO_write(rbio, iv, sizeof(iv));
+    BIO_write(rbio, enc, len);
+
+    OPENSSL_free(enc);
+    return 1;
+}
+
+static int send_finished(SSL *s, BIO *rbio)
+{
+    static unsigned char finished_msg[DTLS1_HM_HEADER_LENGTH +
+                                      TLS1_FINISH_MAC_LENGTH] = {
+        0x14, /* Finished */
+        0x00, 0x00, 0x0c, /* Length */
+        0x00, 0x03, /* Seq# 3 */
+        0x00, 0x00, 0x00, /* Fragment offset */
+        0x00, 0x00, 0x0c, /* Fragment length */
+        /* Finished MAC (12 bytes) */
+    };
+    unsigned char handshake_hash[EVP_MAX_MD_SIZE];
+
+    /* Derive key material */
+    do_PRF(TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE,
+           server_random, SSL3_RANDOM_SIZE,
+           client_random, SSL3_RANDOM_SIZE,
+           key_block, sizeof(key_block));
+
+    /* Generate Finished MAC */
+    if (!EVP_DigestFinal_ex(handshake_md, handshake_hash, NULL))
+        printf("EVP_DigestFinal_ex() failed\n");
+
+    do_PRF(TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE,
+           handshake_hash, EVP_MD_CTX_size(handshake_md),
+           NULL, 0,
+           finished_msg + DTLS1_HM_HEADER_LENGTH, TLS1_FINISH_MAC_LENGTH);
+
+    return send_record(rbio, SSL3_RT_HANDSHAKE, 0,
+                       finished_msg, sizeof(finished_msg));
+}
+
+static int validate_ccs(BIO *wbio)
+{
+    PACKET pkt;
+    long len;
+    unsigned char *data;
+    unsigned int u;
+
+    len = BIO_get_mem_data(wbio, (char **)&data);
+    if (!PACKET_buf_init(&pkt, data, len))
+        return 0;
+
+    /* Check record header type */
+    if (!PACKET_get_1(&pkt, &u) || u != SSL3_RT_CHANGE_CIPHER_SPEC)
+        return 0;
+    /* Version */
+    if (!PACKET_get_net_2(&pkt, &u) || u != DTLS1_BAD_VER)
+        return 0;
+    /* Skip the rest of the record header */
+    if (!PACKET_forward(&pkt, DTLS1_RT_HEADER_LENGTH - 3))
+        return 0;
+
+    /* Check ChangeCipherSpec message */
+    if (!PACKET_get_1(&pkt, &u) || u != SSL3_MT_CCS)
+        return 0;
+    /* A DTLS1_BAD_VER ChangeCipherSpec also contains the
+     * handshake sequence number (which is 2 here) */
+    if (!PACKET_get_net_2(&pkt, &u) || u != 0x0002)
+        return 0;
+
+    /* Now check the Finished packet */
+    if (!PACKET_get_1(&pkt, &u) || u != SSL3_RT_HANDSHAKE)
+        return 0;
+    if (!PACKET_get_net_2(&pkt, &u) || u != DTLS1_BAD_VER)
+        return 0;
+
+    /* Check epoch is now 1 */
+    if (!PACKET_get_net_2(&pkt, &u) || u != 0x0001)
+        return 0;
+
+    /* That'll do for now. If OpenSSL accepted *our* Finished packet
+     * then it's evidently remembered that DTLS1_BAD_VER doesn't
+     * include the handshake header in the MAC. There's not a lot of
+     * point in implementing decryption here, just to check that it
+     * continues to get it right for one more packet. */
+
+    return 1;
+}
+
+#define NODROP(x) { x##UL, 0 }
+#define DROP(x)   { x##UL, 1 }
+
+static struct {
+    unsigned long seq;
+    int drop;
+} tests[] = {
+    NODROP(1), NODROP(3), NODROP(2),
+    NODROP(0x1234), NODROP(0x1230), NODROP(0x1235),
+    NODROP(0xffff), NODROP(0x10001), NODROP(0xfffe), NODROP(0x10000),
+    DROP(0x10001), DROP(0xff), NODROP(0x100000), NODROP(0x800000), NODROP(0x7fffe1),
+    NODROP(0xffffff), NODROP(0x1000000), NODROP(0xfffffe), DROP(0xffffff), NODROP(0x1000010),
+    NODROP(0xfffffd), NODROP(0x1000011), DROP(0x12), NODROP(0x1000012),
+    NODROP(0x1ffffff), NODROP(0x2000000), DROP(0x1ff00fe), NODROP(0x2000001),
+    NODROP(0x20fffff), NODROP(0x2105500), DROP(0x20ffffe), NODROP(0x21054ff),
+    NODROP(0x211ffff), DROP(0x2110000), NODROP(0x2120000)
+    /* The last test should be NODROP, because a DROP wouldn't get tested. */
+};
+
+int main(int argc, char *argv[])
+{
+    SSL_SESSION *sess;
+    SSL_CTX *ctx;
+    SSL *con;
+    BIO *rbio;
+    BIO *wbio;
+    BIO *err;
+    int testresult = 0;
+    int ret;
+    int i;
+
+    err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT);
+
+    CRYPTO_set_mem_debug(1);
+    CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
+
+    RAND_bytes(session_id, sizeof(session_id));
+    RAND_bytes(master_secret, sizeof(master_secret));
+    RAND_bytes(cookie, sizeof(cookie));
+    RAND_bytes(server_random + 4, sizeof(server_random) - 4);
+    time((void *)server_random);
+
+    sess = client_session();
+    if (sess == NULL) {
+        printf("Failed to generate SSL_SESSION\n");
+        goto end;
+    }
+
+    handshake_md = EVP_MD_CTX_new();
+    if (handshake_md == NULL ||
+        !EVP_DigestInit_ex(handshake_md, EVP_md5_sha1(), NULL)) {
+        printf("Failed to initialise handshake_md\n");
+        goto end;
+    }
+
+    ctx = SSL_CTX_new(DTLS_client_method());
+    if (ctx == NULL) {
+        printf("Failed to allocate SSL_CTX\n");
+        goto end_md;
+    }
+    if (!SSL_CTX_set_min_proto_version(ctx, DTLS1_BAD_VER)) {
+        printf("SSL_CTX_set_min_proto_version() failed\n");
+        goto end_ctx;
+    }
+    if (!SSL_CTX_set_max_proto_version(ctx, DTLS1_BAD_VER)) {
+        printf("SSL_CTX_set_max_proto_version() failed\n");
+        goto end_ctx;
+    }
+
+    if (!SSL_CTX_set_cipher_list(ctx, "AES128-SHA")) {
+        printf("SSL_CTX_set_cipher_list() failed\n");
+        goto end_ctx;
+    }
+
+    con = SSL_new(ctx);
+    if (!SSL_set_session(con, sess)) {
+        printf("SSL_set_session() failed\n");
+        goto end_con;
+    }
+    SSL_SESSION_free(sess);
+
+    rbio = BIO_new(BIO_s_mem());
+    wbio = BIO_new(BIO_s_mem());
+
+    BIO_set_nbio(rbio, 1);
+    BIO_set_nbio(wbio, 1);
+
+    SSL_set_bio(con, rbio, wbio);
+    SSL_set_connect_state(con);
+
+    /* Send initial ClientHello */
+    ret = SSL_do_handshake(con);
+    if (ret > 0 || SSL_get_error(con, ret) != SSL_ERROR_WANT_READ) {
+        printf("Unexpected handshake result at initial call!\n");
+        goto end_con;
+    }
+
+    if (validate_client_hello(wbio) != 1) {
+        printf("Initial ClientHello failed validation\n");
+        goto end_con;
+    }
+    if (send_hello_verify(rbio) != 1) {
+        printf("Failed to send HelloVerify\n");
+        goto end_con;
+    }
+    ret = SSL_do_handshake(con);
+    if (ret > 0 || SSL_get_error(con, ret) != SSL_ERROR_WANT_READ) {
+        printf("Unexpected handshake result after HelloVerify!\n");
+        goto end_con;
+    }
+    if (validate_client_hello(wbio) != 2) {
+        printf("Second ClientHello failed validation\n");
+        goto end_con;
+    }
+    if (send_server_hello(rbio) != 1) {
+        printf("Failed to send ServerHello\n");
+        goto end_con;
+    }
+    ret = SSL_do_handshake(con);
+    if (ret > 0 || SSL_get_error(con, ret) != SSL_ERROR_WANT_READ) {
+        printf("Unexpected handshake result after ServerHello!\n");
+        goto end_con;
+    }
+    if (send_finished(con, rbio) != 1) {
+        printf("Failed to send Finished\n");
+        goto end_con;
+    }
+    ret = SSL_do_handshake(con);
+    if (ret < 1) {
+        printf("Handshake not successful after Finished!\n");
+        goto end_con;
+    }
+    if (validate_ccs(wbio) != 1) {
+        printf("Failed to validate client CCS/Finished\n");
+        goto end_con;
+    }
+
+    /* While we're here and crafting packets by hand, we might as well do a
+       bit of a stress test on the DTLS record replay handling. Not Cisco-DTLS
+       specific but useful anyway for the general case. It's been broken
+       before, and in fact was broken even for a basic 0, 2, 1 test case
+       when this test was first added.... */
+    for (i = 0; i < (int)OSSL_NELEM(tests); i++) {
+        unsigned long recv_buf[2];
+
+        if (send_record(rbio, SSL3_RT_APPLICATION_DATA, tests[i].seq,
+                        &tests[i].seq, sizeof(unsigned long)) != 1) {
+            printf("Failed to send data seq #0x%lx (%d)\n",
+                   tests[i].seq, i);
+            goto end_con;
+        }
+
+        if (tests[i].drop)
+            continue;
+
+        ret = SSL_read(con, recv_buf, 2 * sizeof(unsigned long));
+        if (ret != sizeof(unsigned long)) {
+            printf("SSL_read failed or wrong size on seq#0x%lx (%d)\n",
+                   tests[i].seq, i);
+            goto end_con;
+        }
+        if (recv_buf[0] != tests[i].seq) {
+            printf("Wrong data packet received (0x%lx not 0x%lx) at packet %d\n",
+                   recv_buf[0], tests[i].seq, i);
+            goto end_con;
+        }
+    }
+    if (tests[i-1].drop) {
+        printf("Error: last test cannot be DROP()\n");
+        goto end_con;
+    }
+    testresult=1;
+
+ end_con:
+    SSL_free(con);
+ end_ctx:
+    SSL_CTX_free(ctx);
+ end_md:
+    EVP_MD_CTX_free(handshake_md);
+ end:
+    ERR_print_errors_fp(stderr);
+
+    if (!testresult) {
+        printf("Cisco BadDTLS test: FAILED\n");
+    }
+
+
+#ifndef OPENSSL_NO_CRYPTO_MDEBUG
+    if (CRYPTO_mem_leaks(err) <= 0)
+        testresult = 0;
+#endif
+    BIO_free(err);
+
+    return testresult?0:1;
+}
diff --git a/test/build.info b/test/build.info
index 4e1ec65..7edd12e 100644
--- a/test/build.info
+++ b/test/build.info
@@ -11,7 +11,7 @@ IF[{- !$disabled{tests} -}]
           randtest dhtest enginetest casttest \
           bftest ssltest_old dsatest exptest rsa_test \
           evp_test evp_extra_test igetest v3nametest v3ext \
-          danetest heartbeat_test p5_crpt2_test \
+          danetest heartbeat_test p5_crpt2_test bad_dtls_test \
           constant_time_test verify_extra_test clienthellotest \
           packettest asynctest secmemtest srptest memleaktest \
           dtlsv1listentest ct_test threadstest afalgtest d2i_test \
@@ -190,6 +190,10 @@ IF[{- !$disabled{tests} -}]
   INCLUDE[clienthellotest]=../include
   DEPEND[clienthellotest]=../libcrypto ../libssl
 
+  SOURCE[bad_dtls_test]=bad_dtls_test.c
+  INCLUDE[bad_dtls_test]=.. ../include
+  DEPEND[bad_dtls_test]=../libcrypto ../libssl
+
   SOURCE[packettest]=packettest.c
   INCLUDE[packettest]=../include
   DEPEND[packettest]=../libcrypto
diff --git a/test/recipes/90-test_bioprint.t b/test/recipes/70-test_bad_dtls.t
similarity index 58%
copy from test/recipes/90-test_bioprint.t
copy to test/recipes/70-test_bad_dtls.t
index b86e828..a20db77 100644
--- a/test/recipes/90-test_bioprint.t
+++ b/test/recipes/70-test_bad_dtls.t
@@ -7,6 +7,14 @@
 # https://www.openssl.org/source/license.html
 
 
-use OpenSSL::Test::Simple;
+use OpenSSL::Test;
+use OpenSSL::Test::Utils;
 
-simple_test("test_bioprint", "bioprinttest");
+setup("test_bad_dtls");
+
+plan skip_all => "DTLSv1 is not supported by this OpenSSL build"
+    if disabled("dtls1");
+
+plan tests => 1;
+
+ok(run(test(["bad_dtls_test"])), "running bad_dtls_test");


More information about the openssl-commits mailing list