Fix end-point shared secret for DTLS/SCTP
authorMichael Tuexen <tuexen@fh-muenster.de>
Wed, 26 Dec 2018 11:44:53 +0000 (12:44 +0100)
committerMatt Caswell <matt@openssl.org>
Fri, 1 Feb 2019 11:57:19 +0000 (11:57 +0000)
When computing the end-point shared secret, don't take the
terminating NULL character into account.
Please note that this fix breaks interoperability with older
versions of OpenSSL, which are not fixed.

Fixes #7956

Reviewed-by: Kurt Roeckx <kurt@roeckx.be>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/7957)

15 files changed:
CHANGES
apps/s_client.c
apps/s_server.c
doc/man1/s_client.pod
doc/man1/s_server.pod
doc/man3/SSL_CTX_set_mode.pod
include/openssl/ssl.h
ssl/statem/statem_clnt.c
ssl/statem/statem_srvr.c
test/handshake_helper.c
test/recipes/80-test_ssl_new.t
test/ssl-tests/29-dtls-sctp-label-bug.conf [new file with mode: 0644]
test/ssl-tests/29-dtls-sctp-label-bug.conf.in [new file with mode: 0644]
test/ssl_test_ctx.c
test/ssl_test_ctx.h

diff --git a/CHANGES b/CHANGES
index 311d6c6..20b1f5c 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -9,6 +9,13 @@
 
  Changes between 1.1.1 and 3.0.0 [xx XXX xxxx]
 
+  *) Fix a bug in the computation of the endpoint-pair shared secret used
+     by DTLS over SCTP. This breaks interoperability with older versions
+     of OpenSSL like OpenSSL 1.1.0 and OpenSSL 1.0.2. There is a runtime
+     switch SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG (off by default) enabling
+     interoperability with such broken implementations. However, enabling
+     this switch breaks interoperability with correct implementations.
+
   *) Move strictness check from EVP_PKEY_asn1_new() to EVP_PKEY_asn1_add0().
      [Richard Levitte]
 
index 6e06f15..872496c 100644 (file)
@@ -598,6 +598,7 @@ typedef enum OPTION_choice {
 #endif
     OPT_DANE_TLSA_RRDATA, OPT_DANE_EE_NO_NAME,
     OPT_ENABLE_PHA,
+    OPT_SCTP_LABEL_BUG,
     OPT_R_ENUM
 } OPTION_CHOICE;
 
@@ -754,6 +755,7 @@ const OPTIONS s_client_options[] = {
 #endif
 #ifndef OPENSSL_NO_SCTP
     {"sctp", OPT_SCTP, '-', "Use SCTP"},
+    {"sctp_label_bug", OPT_SCTP_LABEL_BUG, '-', "Enable SCTP label length bug"},
 #endif
 #ifndef OPENSSL_NO_SSL_TRACE
     {"trace", OPT_TRACE, '-', "Show trace output of protocol messages"},
@@ -982,6 +984,9 @@ int s_client_main(int argc, char **argv)
 #endif
     char *psksessf = NULL;
     int enable_pha = 0;
+#ifndef OPENSSL_NO_SCTP
+    int sctp_label_bug = 0;
+#endif
 
     FD_ZERO(&readfds);
     FD_ZERO(&writefds);
@@ -1335,6 +1340,11 @@ int s_client_main(int argc, char **argv)
             protocol = IPPROTO_SCTP;
 #endif
             break;
+        case OPT_SCTP_LABEL_BUG:
+#ifndef OPENSSL_NO_SCTP
+            sctp_label_bug = 1;
+#endif
+            break;
         case OPT_TIMEOUT:
 #ifndef OPENSSL_NO_DTLS
             enable_timeouts = 1;
@@ -1729,6 +1739,11 @@ int s_client_main(int argc, char **argv)
         }
     }
 
+#ifndef OPENSSL_NO_SCTP
+    if (protocol == IPPROTO_SCTP && sctp_label_bug == 1)
+        SSL_CTX_set_mode(ctx, SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG);
+#endif
+
     if (min_version != 0
         && SSL_CTX_set_min_proto_version(ctx, min_version) == 0)
         goto end;
index 8565a3a..fbbfd6c 100644 (file)
@@ -751,7 +751,7 @@ typedef enum OPTION_choice {
     OPT_CERT2, OPT_KEY2, OPT_NEXTPROTONEG, OPT_ALPN,
     OPT_SRTP_PROFILES, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN,
     OPT_KEYLOG_FILE, OPT_MAX_EARLY, OPT_RECV_MAX_EARLY, OPT_EARLY_DATA,
-    OPT_S_NUM_TICKETS, OPT_ANTI_REPLAY, OPT_NO_ANTI_REPLAY,
+    OPT_S_NUM_TICKETS, OPT_ANTI_REPLAY, OPT_NO_ANTI_REPLAY, OPT_SCTP_LABEL_BUG,
     OPT_R_ENUM,
     OPT_S_ENUM,
     OPT_V_ENUM,
@@ -938,6 +938,7 @@ const OPTIONS s_server_options[] = {
 #endif
 #ifndef OPENSSL_NO_SCTP
     {"sctp", OPT_SCTP, '-', "Use SCTP"},
+    {"sctp_label_bug", OPT_SCTP_LABEL_BUG, '-', "Enable SCTP label length bug"},
 #endif
 #ifndef OPENSSL_NO_DH
     {"no_dhe", OPT_NO_DHE, '-', "Disable ephemeral DH"},
@@ -1047,6 +1048,9 @@ int s_server_main(int argc, char *argv[])
     const char *keylog_file = NULL;
     int max_early_data = -1, recv_max_early_data = -1;
     char *psksessf = NULL;
+#ifndef OPENSSL_NO_SCTP
+    int sctp_label_bug = 0;
+#endif
 
     /* Init of few remaining global variables */
     local_argc = argc;
@@ -1490,6 +1494,11 @@ int s_server_main(int argc, char *argv[])
             protocol = IPPROTO_SCTP;
 #endif
             break;
+        case OPT_SCTP_LABEL_BUG:
+#ifndef OPENSSL_NO_SCTP
+            sctp_label_bug = 1;
+#endif
+            break;
         case OPT_TIMEOUT:
 #ifndef OPENSSL_NO_DTLS
             enable_timeouts = 1;
@@ -1792,6 +1801,12 @@ int s_server_main(int argc, char *argv[])
             goto end;
         }
     }
+
+#ifndef OPENSSL_NO_SCTP
+    if (protocol == IPPROTO_SCTP && sctp_label_bug == 1)
+        SSL_CTX_set_mode(ctx, SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG);
+#endif
+
     if (min_version != 0
         && SSL_CTX_set_min_proto_version(ctx, min_version) == 0)
         goto end;
index 70b97bf..e16450b 100644 (file)
@@ -102,6 +102,7 @@ B<openssl> B<s_client>
 [B<-dtls1>]
 [B<-dtls1_2>]
 [B<-sctp>]
+[B<-sctp_label_bug>]
 [B<-fallback_scsv>]
 [B<-async>]
 [B<-max_send_frag>]
@@ -506,6 +507,14 @@ Use SCTP for the transport protocol instead of UDP in DTLS. Must be used in
 conjunction with B<-dtls>, B<-dtls1> or B<-dtls1_2>. This option is only
 available where OpenSSL has support for SCTP enabled.
 
+=item B<-sctp_label_bug>
+
+Use the incorrect behaviour of older OpenSSL implementations when computing
+endpoint-pair shared secrets for DTLS/SCTP. This allows communication with
+older broken implementations but breaks interoperability with correct
+implementations. Must be used in conjunction with B<-sctp>. This option is only
+available where OpenSSL has support for SCTP enabled.
+
 =item B<-fallback_scsv>
 
 Send TLS_FALLBACK_SCSV in the ClientHello.
index e86c2b3..c4f1bba 100644 (file)
@@ -173,6 +173,7 @@ B<openssl> B<s_server>
 [B<-dtls1>]
 [B<-dtls1_2>]
 [B<-sctp>]
+[B<-sctp_label_bug>]
 [B<-no_dhe>]
 [B<-nextprotoneg val>]
 [B<-use_srtp val>]
@@ -685,6 +686,14 @@ Use SCTP for the transport protocol instead of UDP in DTLS. Must be used in
 conjunction with B<-dtls>, B<-dtls1> or B<-dtls1_2>. This option is only
 available where OpenSSL has support for SCTP enabled.
 
+=item B<-sctp_label_bug>
+
+Use the incorrect behaviour of older OpenSSL implementations when computing
+endpoint-pair shared secrets for DTLS/SCTP. This allows communication with
+older broken implementations but breaks interoperability with correct
+implementations. Must be used in conjunction with B<-sctp>. This option is only
+available where OpenSSL has support for SCTP enabled.
+
 =item B<-no_dhe>
 
 If this option is set then no DH parameters will be loaded effectively
index 06e9a29..a4997c9 100644 (file)
@@ -121,6 +121,15 @@ Kernel TLS might not support all the features of OpenSSL. For instance,
 renegotiation, and setting the maximum fragment size is not possible as of
 Linux 4.20.
 
+=item SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG
+
+Older versions of OpenSSL had a bug in the computation of the label length
+used for computing the endpoint-pair shared secret. The bug was that the
+terminating zero was included in the length of the label. Setting this option
+enables this behaviour to allow interoperability with such broken
+implementations. Please note that setting this option breaks interoperability
+with correct implementations. This option only applies to DTLS over SCTP.
+
 =back
 
 All modes are off by default except for SSL_MODE_AUTO_RETRY which is on by
index c7a8304..dc7285f 100644 (file)
@@ -500,6 +500,18 @@ typedef int (*SSL_async_callback_fn)(SSL *s, void *arg);
  * Use the kernel TLS transmission data-path.
  */
 # define SSL_MODE_NO_KTLS_TX 0x00000200U
+/*
+ * When using DTLS/SCTP, include the terminating zero in the label
+ * used for computing the endpoint-pair shared secret. Required for
+ * interoperability with implementations having this bug like these
+ * older version of OpenSSL:
+ * - OpenSSL 1.0.0 series
+ * - OpenSSL 1.0.1 series
+ * - OpenSSL 1.0.2 series
+ * - OpenSSL 1.1.0 series
+ * - OpenSSL 1.1.1 and 1.1.1a
+ */
+# define SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG 0x00000400U
 
 /* Cert related flags */
 /*
index 53bc5ef..1f55113 100644 (file)
@@ -1707,6 +1707,7 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
     if (SSL_IS_DTLS(s) && s->hit) {
         unsigned char sctpauthkey[64];
         char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
+        size_t labellen;
 
         /*
          * Add new shared key for SCTP-Auth, will be ignored if
@@ -1715,10 +1716,15 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
         memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL,
                sizeof(DTLS1_SCTP_AUTH_LABEL));
 
+        /* Don't include the terminating zero. */
+        labellen = sizeof(labelbuffer) - 1;
+        if (s->mode & SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG)
+            labellen += 1;
+
         if (SSL_export_keying_material(s, sctpauthkey,
                                        sizeof(sctpauthkey),
                                        labelbuffer,
-                                       sizeof(labelbuffer), NULL, 0, 0) <= 0) {
+                                       labellen, NULL, 0, 0) <= 0) {
             SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
                      ERR_R_INTERNAL_ERROR);
             goto err;
@@ -3397,6 +3403,7 @@ int tls_client_key_exchange_post_work(SSL *s)
     if (SSL_IS_DTLS(s)) {
         unsigned char sctpauthkey[64];
         char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
+        size_t labellen;
 
         /*
          * Add new shared key for SCTP-Auth, will be ignored if no SCTP
@@ -3405,9 +3412,14 @@ int tls_client_key_exchange_post_work(SSL *s)
         memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL,
                sizeof(DTLS1_SCTP_AUTH_LABEL));
 
+        /* Don't include the terminating zero. */
+        labellen = sizeof(labelbuffer) - 1;
+        if (s->mode & SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG)
+            labellen += 1;
+
         if (SSL_export_keying_material(s, sctpauthkey,
                                        sizeof(sctpauthkey), labelbuffer,
-                                       sizeof(labelbuffer), NULL, 0, 0) <= 0) {
+                                       labellen, NULL, 0, 0) <= 0) {
             SSLfatal(s, SSL_AD_INTERNAL_ERROR,
                      SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK,
                      ERR_R_INTERNAL_ERROR);
index b0dd549..f76568c 100644 (file)
@@ -830,6 +830,7 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
         if (SSL_IS_DTLS(s) && s->hit) {
             unsigned char sctpauthkey[64];
             char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
+            size_t labellen;
 
             /*
              * Add new shared key for SCTP-Auth, will be ignored if no
@@ -838,9 +839,14 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
             memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL,
                    sizeof(DTLS1_SCTP_AUTH_LABEL));
 
+            /* Don't include the terminating zero. */
+            labellen = sizeof(labelbuffer) - 1;
+            if (s->mode & SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG)
+                labellen += 1;
+
             if (SSL_export_keying_material(s, sctpauthkey,
                                            sizeof(sctpauthkey), labelbuffer,
-                                           sizeof(labelbuffer), NULL, 0,
+                                           labellen, NULL, 0,
                                            0) <= 0) {
                 SSLfatal(s, SSL_AD_INTERNAL_ERROR,
                          SSL_F_OSSL_STATEM_SERVER_POST_WORK,
@@ -3500,6 +3506,7 @@ WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst)
         if (SSL_IS_DTLS(s)) {
             unsigned char sctpauthkey[64];
             char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
+            size_t labellen;
             /*
              * Add new shared key for SCTP-Auth, will be ignored if no SCTP
              * used.
@@ -3507,9 +3514,14 @@ WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst)
             memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL,
                    sizeof(DTLS1_SCTP_AUTH_LABEL));
 
+            /* Don't include the terminating zero. */
+            labellen = sizeof(labelbuffer) - 1;
+            if (s->mode & SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG)
+                labellen += 1;
+
             if (SSL_export_keying_material(s, sctpauthkey,
                                            sizeof(sctpauthkey), labelbuffer,
-                                           sizeof(labelbuffer), NULL, 0,
+                                           labellen, NULL, 0,
                                            0) <= 0) {
                 SSLfatal(s, SSL_AD_INTERNAL_ERROR,
                          SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE,
index a9ef753..a85d22e 100644 (file)
 #include "handshake_helper.h"
 #include "testutil.h"
 
+#if !defined(OPENSSL_NO_SCTP) && !defined(OPENSSL_NO_SOCK)
+#include <netinet/sctp.h>
+#endif
+
 HANDSHAKE_RESULT *HANDSHAKE_RESULT_new(void)
 {
     HANDSHAKE_RESULT *ret;
@@ -1282,13 +1286,33 @@ static int peer_pkey_type(SSL *s)
 #if !defined(OPENSSL_NO_SCTP) && !defined(OPENSSL_NO_SOCK)
 static int set_sock_as_sctp(int sock)
 {
+    struct sctp_assocparams assocparams;
+    struct sctp_rtoinfo rto_info;
+    BIO *tmpbio;
+
+    /*
+     * To allow tests to fail fast (within a second or so), reduce the
+     * retransmission timeouts and the number of retransmissions.
+     */
+    memset(&rto_info, 0, sizeof(struct sctp_rtoinfo));
+    rto_info.srto_initial = 100;
+    rto_info.srto_max = 200;
+    rto_info.srto_min = 50;
+    (void)setsockopt(sock, IPPROTO_SCTP, SCTP_RTOINFO,
+                     (const void *)&rto_info, sizeof(struct sctp_rtoinfo));
+    memset(&assocparams, 0, sizeof(struct sctp_assocparams));
+    assocparams.sasoc_asocmaxrxt = 2;
+    (void)setsockopt(sock, IPPROTO_SCTP, SCTP_ASSOCINFO,
+                     (const void *)&assocparams,
+                     sizeof(struct sctp_assocparams));
+
     /*
      * For SCTP we have to set various options on the socket prior to
      * connecting. This is done automatically by BIO_new_dgram_sctp().
      * We don't actually need the created BIO though so we free it again
      * immediately.
      */
-    BIO *tmpbio = BIO_new_dgram_sctp(sock, BIO_NOCLOSE);
+    tmpbio = BIO_new_dgram_sctp(sock, BIO_NOCLOSE);
 
     if (tmpbio == NULL)
         return 0;
@@ -1438,6 +1462,13 @@ static HANDSHAKE_RESULT *do_handshake_internal(
         return NULL;
     }
 
+#if !defined(OPENSSL_NO_SCTP) && !defined(OPENSSL_NO_SOCK)
+    if (test_ctx->enable_client_sctp_label_bug)
+        SSL_CTX_set_mode(client_ctx, SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG);
+    if (test_ctx->enable_server_sctp_label_bug)
+        SSL_CTX_set_mode(server_ctx, SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG);
+#endif
+
     /* Setup SSL and buffers; additional configuration happens below. */
     if (!create_peer(&server, server_ctx)) {
         TEST_note("creating server context");
index ecec3c9..fa98f24 100644 (file)
@@ -28,7 +28,7 @@ map { s/\^// } @conf_files if $^O eq "VMS";
 
 # We hard-code the number of tests to double-check that the globbing above
 # finds all files as expected.
-plan tests => 28;  # = scalar @conf_srcs
+plan tests => 29;  # = scalar @conf_srcs
 
 # Some test results depend on the configuration of enabled protocols. We only
 # verify generated sources in the default configuration.
@@ -102,6 +102,7 @@ my %skip = (
   "24-padding.conf" => disabled("tls1_3"),
   "25-cipher.conf" => disabled("ec") || disabled("tls1_2"),
   "26-tls13_client_auth.conf" => disabled("tls1_3"),
+  "29-dtls-sctp-label-bug.conf" => disabled("sctp") || disabled("sock"),
 );
 
 foreach my $conf (@conf_files) {
diff --git a/test/ssl-tests/29-dtls-sctp-label-bug.conf b/test/ssl-tests/29-dtls-sctp-label-bug.conf
new file mode 100644 (file)
index 0000000..24f9e04
--- /dev/null
@@ -0,0 +1,116 @@
+# Generated with generate_ssl_tests.pl
+
+num_tests = 4
+
+test-0 = 0-SCTPLabelBug-good1
+test-1 = 1-SCTPLabelBug-good2
+test-2 = 2-SCTPLabelBug-bad1
+test-3 = 3-SCTPLabelBug-bad2
+# ===========================================================
+
+[0-SCTPLabelBug-good1]
+ssl_conf = 0-SCTPLabelBug-good1-ssl
+
+[0-SCTPLabelBug-good1-ssl]
+server = 0-SCTPLabelBug-good1-server
+client = 0-SCTPLabelBug-good1-client
+
+[0-SCTPLabelBug-good1-server]
+Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+CipherString = DEFAULT
+PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+
+[0-SCTPLabelBug-good1-client]
+CipherString = DEFAULT
+VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+VerifyMode = Peer
+
+[test-0]
+EnableClientSCTPLabelBug = No
+EnableServerSCTPLabelBug = No
+ExpectedResult = Success
+Method = DTLS
+UseSCTP = Yes
+
+
+# ===========================================================
+
+[1-SCTPLabelBug-good2]
+ssl_conf = 1-SCTPLabelBug-good2-ssl
+
+[1-SCTPLabelBug-good2-ssl]
+server = 1-SCTPLabelBug-good2-server
+client = 1-SCTPLabelBug-good2-client
+
+[1-SCTPLabelBug-good2-server]
+Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+CipherString = DEFAULT
+PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+
+[1-SCTPLabelBug-good2-client]
+CipherString = DEFAULT
+VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+VerifyMode = Peer
+
+[test-1]
+EnableClientSCTPLabelBug = Yes
+EnableServerSCTPLabelBug = Yes
+ExpectedResult = Success
+Method = DTLS
+UseSCTP = Yes
+
+
+# ===========================================================
+
+[2-SCTPLabelBug-bad1]
+ssl_conf = 2-SCTPLabelBug-bad1-ssl
+
+[2-SCTPLabelBug-bad1-ssl]
+server = 2-SCTPLabelBug-bad1-server
+client = 2-SCTPLabelBug-bad1-client
+
+[2-SCTPLabelBug-bad1-server]
+Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+CipherString = DEFAULT
+PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+
+[2-SCTPLabelBug-bad1-client]
+CipherString = DEFAULT
+VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+VerifyMode = Peer
+
+[test-2]
+EnableClientSCTPLabelBug = Yes
+EnableServerSCTPLabelBug = No
+ExpectedResult = ClientFail
+Method = DTLS
+UseSCTP = Yes
+
+
+# ===========================================================
+
+[3-SCTPLabelBug-bad2]
+ssl_conf = 3-SCTPLabelBug-bad2-ssl
+
+[3-SCTPLabelBug-bad2-ssl]
+server = 3-SCTPLabelBug-bad2-server
+client = 3-SCTPLabelBug-bad2-client
+
+[3-SCTPLabelBug-bad2-server]
+Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
+CipherString = DEFAULT
+PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
+
+[3-SCTPLabelBug-bad2-client]
+CipherString = DEFAULT
+VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
+VerifyMode = Peer
+
+[test-3]
+EnableClientSCTPLabelBug = No
+EnableServerSCTPLabelBug = Yes
+ExpectedResult = ClientFail
+Method = DTLS
+UseSCTP = Yes
+
+
diff --git a/test/ssl-tests/29-dtls-sctp-label-bug.conf.in b/test/ssl-tests/29-dtls-sctp-label-bug.conf.in
new file mode 100644 (file)
index 0000000..ab04d05
--- /dev/null
@@ -0,0 +1,67 @@
+# -*- mode: perl; -*-
+# Copyright 2019-2019 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the Apache License 2.0 (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
+
+
+## Test SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG handling
+
+use strict;
+use warnings;
+
+package ssltests;
+use OpenSSL::Test::Utils;
+
+our @tests = (
+    {
+        name => "SCTPLabelBug-good1",
+        server => {},
+        client => {},
+        test => {
+            "Method" => "DTLS",
+            "UseSCTP" => "Yes",
+            "EnableClientSCTPLabelBug" => "No",
+            "EnableServerSCTPLabelBug" => "No",
+            "ExpectedResult" => "Success"
+        }
+    },
+    {
+        name => "SCTPLabelBug-good2",
+        server => {},
+        client => {},
+        test => {
+            "Method" => "DTLS",
+            "UseSCTP" => "Yes",
+            "EnableClientSCTPLabelBug" => "Yes",
+            "EnableServerSCTPLabelBug" => "Yes",
+            "ExpectedResult" => "Success"
+        }
+    },
+    {
+        name => "SCTPLabelBug-bad1",
+        server => {},
+        client => {},
+        test => {
+            "Method" => "DTLS",
+            "UseSCTP" => "Yes",
+            "EnableClientSCTPLabelBug" => "Yes",
+            "EnableServerSCTPLabelBug" => "No",
+            "ExpectedResult" => "ClientFail"
+        }
+    },
+    {
+        name => "SCTPLabelBug-bad2",
+        server => {},
+        client => {},
+        test => {
+            "Method" => "DTLS",
+            "UseSCTP" => "Yes",
+            "EnableClientSCTPLabelBug" => "No",
+            "EnableServerSCTPLabelBug" => "Yes",
+            "ExpectedResult" => "ClientFail"
+        }
+    },
+);
index 3b7cc3e..6a3b66b 100644 (file)
@@ -446,6 +446,8 @@ const char *ssl_ct_validation_name(ssl_ct_validation_t mode)
 IMPLEMENT_SSL_TEST_BOOL_OPTION(SSL_TEST_CTX, test, resumption_expected)
 IMPLEMENT_SSL_TEST_BOOL_OPTION(SSL_TEST_SERVER_CONF, server, broken_session_ticket)
 IMPLEMENT_SSL_TEST_BOOL_OPTION(SSL_TEST_CTX, test, use_sctp)
+IMPLEMENT_SSL_TEST_BOOL_OPTION(SSL_TEST_CTX, test, enable_client_sctp_label_bug)
+IMPLEMENT_SSL_TEST_BOOL_OPTION(SSL_TEST_CTX, test, enable_server_sctp_label_bug)
 
 /* CertStatus */
 
@@ -669,6 +671,8 @@ static const ssl_test_ctx_option ssl_test_ctx_options[] = {
     { "ExpectedClientSignType", &parse_expected_client_sign_type },
     { "ExpectedClientCANames", &parse_expected_client_ca_names },
     { "UseSCTP", &parse_test_use_sctp },
+    { "EnableClientSCTPLabelBug", &parse_test_enable_client_sctp_label_bug },
+    { "EnableServerSCTPLabelBug", &parse_test_enable_server_sctp_label_bug },
     { "ExpectedCipher", &parse_test_expected_cipher },
     { "ExpectedSessionTicketAppData", &parse_test_expected_session_ticket_app_data },
 };
index 8fa3af0..3a21ac5 100644 (file)
@@ -214,6 +214,10 @@ typedef struct {
     STACK_OF(X509_NAME) *expected_client_ca_names;
     /* Whether to use SCTP for the transport */
     int use_sctp;
+    /* Enable SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG on client side */
+    int enable_client_sctp_label_bug;
+    /* Enable SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG on server side */
+    int enable_server_sctp_label_bug;
     /* Whether to expect a session id from the server */
     ssl_session_id_t session_id_expected;
     char *expected_cipher;