summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGES7
-rw-r--r--apps/s_client.c15
-rw-r--r--apps/s_server.c17
-rw-r--r--doc/man1/s_client.pod9
-rw-r--r--doc/man1/s_server.pod9
-rw-r--r--doc/man3/SSL_CTX_set_mode.pod9
-rw-r--r--include/openssl/ssl.h13
-rw-r--r--ssl/statem/statem_clnt.c16
-rw-r--r--ssl/statem/statem_srvr.c16
-rw-r--r--test/handshake_helper.c33
-rw-r--r--test/recipes/80-test_ssl_new.t3
-rw-r--r--test/ssl-tests/29-dtls-sctp-label-bug.conf116
-rw-r--r--test/ssl-tests/29-dtls-sctp-label-bug.conf.in67
-rw-r--r--test/ssl_test_ctx.c4
-rw-r--r--test/ssl_test_ctx.h4
15 files changed, 331 insertions, 7 deletions
diff --git a/CHANGES b/CHANGES
index d3ad3f6243..261299d44b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -9,6 +9,13 @@
Changes between 1.1.1a and 1.1.1b [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]
diff --git a/apps/s_client.c b/apps/s_client.c
index 5925814871..fb2ff47f19 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -596,6 +596,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;
@@ -750,6 +751,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"},
@@ -976,6 +978,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);
@@ -1323,6 +1328,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;
@@ -1707,6 +1717,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;
diff --git a/apps/s_server.c b/apps/s_server.c
index aa0c9ae681..caf47b35ab 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -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;
diff --git a/doc/man1/s_client.pod b/doc/man1/s_client.pod
index 85179873c2..58fe37a69b 100644
--- a/doc/man1/s_client.pod
+++ b/doc/man1/s_client.pod
@@ -100,6 +100,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>]
@@ -489,6 +490,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.
diff --git a/doc/man1/s_server.pod b/doc/man1/s_server.pod
index 57f2405888..254bfe799b 100644
--- a/doc/man1/s_server.pod
+++ b/doc/man1/s_server.pod
@@ -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
diff --git a/doc/man3/SSL_CTX_set_mode.pod b/doc/man3/SSL_CTX_set_mode.pod
index 76ed717625..4e06eb550a 100644
--- a/doc/man3/SSL_CTX_set_mode.pod
+++ b/doc/man3/SSL_CTX_set_mode.pod
@@ -105,6 +105,15 @@ Enable asynchronous processing. TLS I/O operations may indicate a retry with
SSL_ERROR_WANT_ASYNC with this mode set if an asynchronous capable engine is
used to perform cryptographic operations. See L<SSL_get_error(3)>.
+=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
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index d6b1b4e6a6..e68efa838b 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -494,6 +494,19 @@ typedef int (*SSL_verify_cb)(int preverify_ok, X509_STORE_CTX *x509_ctx);
*/
# define SSL_MODE_ASYNC 0x00000100U
+/*
+ * 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 */
/*
* Many implementations ignore some aspects of the TLS standards such as
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index bb2d98ea24..bb64036491 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -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);
diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c
index a8e862ced5..91c1120db6 100644
--- a/ssl/statem/statem_srvr.c
+++ b/ssl/statem/statem_srvr.c
@@ -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,
diff --git a/test/handshake_helper.c b/test/handshake_helper.c
index 40bfd3ec26..d1842fac8b 100644
--- a/test/handshake_helper.c
+++ b/test/handshake_helper.c
@@ -22,6 +22,10 @@
#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");
diff --git a/test/recipes/80-test_ssl_new.t b/test/recipes/80-test_ssl_new.t
index db2271c388..72220592d1 100644
--- a/test/recipes/80-test_ssl_new.t
+++ b/test/recipes/80-test_ssl_new.t
@@ -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
index 0000000000..24f9e04f16
--- /dev/null
+++ b/test/ssl-tests/29-dtls-sctp-label-bug.conf
@@ -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
index 0000000000..ab04d05264
--- /dev/null
+++ b/test/ssl-tests/29-dtls-sctp-label-bug.conf.in
@@ -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"
+ }
+ },
+);
diff --git a/test/ssl_test_ctx.c b/test/ssl_test_ctx.c
index 753338530d..cc98da240e 100644
--- a/test/ssl_test_ctx.c
+++ b/test/ssl_test_ctx.c
@@ -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 },
};
diff --git a/test/ssl_test_ctx.h b/test/ssl_test_ctx.h
index 86d227d865..4120b8d165 100644
--- a/test/ssl_test_ctx.h
+++ b/test/ssl_test_ctx.h
@@ -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;