Commit 6b01bed2 authored by Viktor Dukhovni's avatar Viktor Dukhovni
Browse files

Support disabling any or all TLS or DTLS versions



Some users want to disable SSL 3.0/TLS 1.0/TLS 1.1, and enable just
TLS 1.2.  In the future they might want to disable TLS 1.2 and
enable just TLS 1.3, ...

This commit makes it possible to disable any or all of the TLS or
DTLS protocols.  It also considerably simplifies the SSL/TLS tests,
by auto-generating the min/max version tests based on the set of
supported protocols (425 explicitly written out tests got replaced
by two loops that generate all 425 tests if all protocols are
enabled, fewer otherwise).

Reviewed-by: default avatarRichard Levitte <levitte@openssl.org>
parent 6ada465f
Loading
Loading
Loading
Loading
+107 −13
Original line number Diff line number Diff line
@@ -820,6 +820,10 @@ my $default_ranlib;
my $perl;
my $fips=0;

# Known TLS and DTLS protocols
my @tls = qw(ssl3 tls1 tls1_1 tls1_2);
my @dtls = qw(dtls1 dtls1_2);

# Explicitelly known options that are possible to disable.  They can
# be regexps, and will be used like this: /^no-${option}$/
# For developers: keep it sorted alphabetically
@@ -847,6 +851,8 @@ my @disablables = (
    "dynamic[-_]engine",
    "ec",
    "ec2m",
    "ecdh",
    "ecdsa",
    "ec_nistp_64_gcc_128",
    "engine",
    "err",			# Really???
@@ -887,20 +893,22 @@ my @disablables = (
    "srtp",
    "sse2",
    "ssl",
    "ssl3",
    "ssl3-method",
    "ssl-trace",
    "static-engine",
    "stdio",
    "store",
    "threads",
    "tls",
    "tls1",
    "unit-test",
    "whirlpool",
    "zlib",
    "zlib-dynamic",
    );
foreach my $proto ((@tls, @dtls))
	{
	push(@disablables, $proto);
	push(@disablables, "$proto-method");
	}

# All of the following is disabled by default (RC5 was enabled before 0.9.8):

@@ -1000,19 +1008,35 @@ PROCESS_ARGS:
			{
			if (!($disabled{$1} eq "experimental"))
				{
				if ($1 eq "ssl")
				foreach my $proto ((@tls, @dtls))
					{
					$disabled{"ssl3"} = "option(ssl)";
					if ($1 eq "$proto-method")
						{
						$disabled{"$proto"} = "option($proto-method)";
						last;
						}
				elsif ($1 eq "tls")
					}
				if ($1 eq "dtls")
					{
                                        foreach my $proto (@dtls)
						{
					$disabled{"tls1"} = "option(tls)"
						$disabled{$proto} = "option(dtls)";
						}
				elsif ($1 eq "ssl3-method")
					}
				elsif ($1 eq "ssl")
					{
					$disabled{"ssl3-method"} = "option(ssl)";
					# Last one of its kind
					$disabled{"ssl3"} = "option(ssl)";
					}
				elsif ($1 eq "tls")
					{
                                        # XXX: Tests will fail if all SSL/TLS
                                        # protocols are disabled.
                                        foreach my $proto (@tls)
						{
						$disabled{$proto} = "option(tls)";
						}
					}
				else
					{
					$disabled{$1} = "option";
@@ -1216,18 +1240,88 @@ if (defined($disabled{"ec"}))
	$disabled{"ecdh"} = "forced";
	}

# SSL 3.0 and TLS requires MD5 and SHA and either RSA or DSA+DH
# SSL 3.0 requires MD5 and SHA and either RSA or DSA+DH
if (defined($disabled{"md5"}) || defined($disabled{"sha"})
    || (defined($disabled{"rsa"})
	&& (defined($disabled{"dsa"}) || defined($disabled{"dh"}))))
	{
	$disabled{"ssl3"} = "forced";
	$disabled{"ssl"} = "forced";
	}

# (D)TLS 1.0 and TLS 1.1 require MD5 and SHA and either RSA or DSA+DH
# or ECDSA + ECDH.  (XXX: We don't support PSK-only builds).
#
if (defined($disabled{"md5"}) || defined($disabled{"sha"})
    || (defined($disabled{"rsa"})
	&& (defined($disabled{"dsa"}) || defined($disabled{"dh"}))
	&& (defined($disabled{"ecdsa"}) || defined($disabled{"ecdh"}))))
	{
	$disabled{"tls1"} = "forced";
	$disabled{"dtls1"} = "forced";
	$disabled{"tls1_1"} = "forced";
	}

# (D)TLS 1.2 requires either RSA or DSA+DH or ECDSA + ECDH
# So if all are missing, we can't do either TLS or DTLS.
# (XXX: We don't support PSK-only builds).
#
if (defined($disabled{"rsa"})
    && (defined($disabled{"dsa"}) || defined($disabled{"dh"}))
    && (defined($disabled{"ecdsa"}) || defined($disabled{"ecdh"})))
	{
	$disabled{"tls"} = "forced";
	$disabled{"dtls"} = "forced";
	foreach my $proto ((@tls, @dtls))
		{
		$disabled{"$proto"} = "forced";
		}
	}


# Avoid protocol support holes.  Also disable all versions below N, if version
# N is disabled while N+1 is enabled.
#
my $prev_disabled = 1;
my $force_disable = 0;
foreach my $proto (reverse(@tls))
	{
	if ($force_disable)
		{
		$disabled{$proto} = 1;
		}
	elsif (! defined($disabled{$proto}))
		{
		$prev_disabled = 0;
		}
	elsif (! $prev_disabled)
		{
		$force_disable = 1;
		}
	}
my $prev_disabled = 1;
my $force_disable = 0;
foreach my $proto (reverse(@dtls))
	{
	if ($force_disable)
		{
		$disabled{$proto} = 1;
		}
	elsif (! defined($disabled{$proto}))
		{
		$prev_disabled = 0;
		}
	elsif (! $prev_disabled)
		{
		$force_disable = 1;
		}
	}

if (defined($disabled{"dgram"}))
	{
	$disabled{"dtls"} = "forced";
	$disabled{"dtls1"} = "forced";
	$disabled{"dtls1_2"} = "forced";
	}

if (defined($disabled{"ec"}) || defined($disabled{"dsa"})
+15 −3
Original line number Diff line number Diff line
@@ -78,15 +78,21 @@ OPTIONS ciphers_options[] = {
    {"v", OPT_V, '-', "Verbose listing of the SSL/TLS ciphers"},
    {"V", OPT_UPPER_V, '-', "Even more verbose"},
    {"s", OPT_S, '-', "Only supported ciphers"},
#ifndef OPENSSL_NO_SSL3
    {"ssl3", OPT_SSL3, '-', "SSL3 mode"},
#endif
#ifndef OPENSSL_NO_TLS1
    {"tls1", OPT_TLS1, '-', "TLS1 mode"},
#endif
#ifndef OPENSSL_NO_TLS1_1
    {"tls1_1", OPT_TLS1_1, '-', "TLS1.1 mode"},
#endif
#ifndef OPENSSL_NO_TLS1_2
    {"tls1_2", OPT_TLS1_2, '-', "TLS1.2 mode"},
#endif
#ifndef OPENSSL_NO_SSL_TRACE
    {"stdname", OPT_STDNAME, '-', "Show standard cipher names"},
#endif
#ifndef OPENSSL_NO_SSL3
    {"ssl3", OPT_SSL3, '-', "SSL3 mode"},
#endif
#ifndef OPENSSL_NO_PSK
    {"psk", OPT_PSK, '-', "include ciphersuites requiring PSK"},
#endif
@@ -153,13 +159,19 @@ int ciphers_main(int argc, char **argv)
#endif
            break;
        case OPT_TLS1:
#ifndef OPENSSL_NO_TLS1
            meth = TLSv1_client_method();
#endif
            break;
        case OPT_TLS1_1:
#ifndef OPENSSL_NO_TLS1_1
            meth = TLSv1_1_client_method();
#endif
            break;
        case OPT_TLS1_2:
#ifndef OPENSSL_NO_TLS1_2
            meth = TLSv1_2_client_method();
#endif
            break;
        case OPT_PSK:
#ifndef OPENSSL_NO_PSK
+21 −0
Original line number Diff line number Diff line
@@ -754,6 +754,12 @@ static void list_disabled(void)
#if defined(OPENSSL_NO_DTLS)
    BIO_puts(bio_out, "DTLS\n");
#endif
#if defined(OPENSSL_NO_DTLS1)
    BIO_puts(bio_out, "DTLS1\n");
#endif
#if defined(OPENSSL_NO_DTLS1_2)
    BIO_puts(bio_out, "DTLS1_2\n");
#endif
#ifdef OPENSSL_NO_EC
    BIO_puts(bio_out, "EC\n");
#endif
@@ -835,9 +841,24 @@ static void list_disabled(void)
#ifdef OPENSSL_NO_SRTP
    BIO_puts(bio_out, "SRTP\n");
#endif
#ifdef OPENSSL_NO_SSL
    BIO_puts(bio_out, "SSL\n");
#endif
#ifdef OPENSSL_NO_SSL3
    BIO_puts(bio_out, "SSL3\n");
#endif
#if defined(OPENSSL_NO_TLS)
    BIO_puts(bio_out, "TLS\n");
#endif
#ifdef OPENSSL_NO_TLS1
    BIO_puts(bio_out, "TLS1\n");
#endif
#ifdef OPENSSL_NO_TLS1_1
    BIO_puts(bio_out, "TLS1_1\n");
#endif
#ifdef OPENSSL_NO_TLS1_2
    BIO_puts(bio_out, "TLS1_2\n");
#endif
#ifdef OPENSSL_NO_WHIRLPOOL
    BIO_puts(bio_out, "WHIRLPOOL\n");
#endif
+31 −14
Original line number Diff line number Diff line
@@ -675,9 +675,6 @@ OPTIONS s_client_options[] = {
    {"quiet", OPT_QUIET, '-', "No s_client output"},
    {"ign_eof", OPT_IGN_EOF, '-', "Ignore input eof (default when -quiet)"},
    {"no_ign_eof", OPT_NO_IGN_EOF, '-', "Don't ignore input eof"},
    {"tls1_2", OPT_TLS1_2, '-', "Just use TLSv1.2"},
    {"tls1_1", OPT_TLS1_1, '-', "Just use TLSv1.1"},
    {"tls1", OPT_TLS1, '-', "Just use TLSv1"},
    {"starttls", OPT_STARTTLS, 's',
     "Use the appropriate STARTTLS command before starting TLS"},
    {"xmpphost", OPT_XMPPHOST, 's',
@@ -727,13 +724,26 @@ OPTIONS s_client_options[] = {
#ifndef OPENSSL_NO_SSL3
    {"ssl3", OPT_SSL3, '-', "Just use SSLv3"},
#endif
#ifndef OPENSSL_NO_TLS1
    {"tls1", OPT_TLS1, '-', "Just use TLSv1"},
#endif
#ifndef OPENSSL_NO_TLS1_1
    {"tls1_1", OPT_TLS1_1, '-', "Just use TLSv1.1"},
#endif
#ifndef OPENSSL_NO_TLS1_2
    {"tls1_2", OPT_TLS1_2, '-', "Just use TLSv1.2"},
#endif
#ifndef OPENSSL_NO_DTLS
    {"dtls", OPT_DTLS, '-'},
    {"dtls1", OPT_DTLS1, '-', "Just use DTLSv1"},
    {"dtls1_2", OPT_DTLS1_2, '-'},
    {"timeout", OPT_TIMEOUT, '-'},
    {"mtu", OPT_MTU, 'p', "Set the link layer MTU"},
#endif
#ifndef OPENSSL_NO_DTLS1
    {"dtls1", OPT_DTLS1, '-', "Just use DTLSv1"},
#endif
#ifndef OPENSSL_NO_DTLS1_2
    {"dtls1_2", OPT_DTLS1_2, '-'},
#endif
#ifndef OPENSSL_NO_SSL_TRACE
    {"trace", OPT_TRACE, '-'},
#endif
@@ -1108,41 +1118,48 @@ int s_client_main(int argc, char **argv)
#endif
            break;
        case OPT_TLS1_2:
#ifndef OPENSSL_NO_TLS1_2
            meth = TLSv1_2_client_method();
#endif
            break;
        case OPT_TLS1_1:
#ifndef OPENSSL_NO_TLS1_1
            meth = TLSv1_1_client_method();
#endif
            break;
        case OPT_TLS1:
#ifndef OPENSSL_NO_TLS1
            meth = TLSv1_client_method();
#endif
            break;
#ifndef OPENSSL_NO_DTLS
        case OPT_DTLS:
#ifndef OPENSSL_NO_DTLS
            meth = DTLS_client_method();
            socket_type = SOCK_DGRAM;
#endif
            break;
        case OPT_DTLS1:
#ifndef OPENSSL_NO_DTLS1
            meth = DTLSv1_client_method();
            socket_type = SOCK_DGRAM;
#endif
            break;
        case OPT_DTLS1_2:
#ifndef OPENSSL_NO_DTLS1_2
            meth = DTLSv1_2_client_method();
            socket_type = SOCK_DGRAM;
#endif
            break;
        case OPT_TIMEOUT:
#ifndef OPENSSL_NO_DTLS
            enable_timeouts = 1;
#endif
            break;
        case OPT_MTU:
#ifndef OPENSSL_NO_DTLS
            socket_mtu = atol(opt_arg());
            break;
#else
        case OPT_DTLS:
        case OPT_DTLS1:
        case OPT_DTLS1_2:
        case OPT_TIMEOUT:
        case OPT_MTU:
            break;
#endif
            break;
        case OPT_FALLBACKSCSV:
            fallback_scsv = 1;
            break;
+43 −28
Original line number Diff line number Diff line
@@ -863,9 +863,6 @@ OPTIONS s_server_options[] = {
     "Do not load certificates from the default certificates directory"},
    {"nocert", OPT_NOCERT, '-', "Don't use any certificates (Anon-DH)"},
    {"quiet", OPT_QUIET, '-', "No server output"},
    {"tls1_2", OPT_TLS1_2, '-', "just talk TLSv1.2"},
    {"tls1_1", OPT_TLS1_1, '-', "Just talk TLSv1.1"},
    {"tls1", OPT_TLS1, '-', "Just talk TLSv1"},
    {"no_resume_ephemeral", OPT_NO_RESUME_EPHEMERAL, '-',
     "Disable caching and tickets if ephemeral (EC)DH is used"},
    {"www", OPT_WWW, '-', "Respond to a 'GET /' with a status page"},
@@ -937,16 +934,29 @@ OPTIONS s_server_options[] = {
#ifndef OPENSSL_NO_SSL3
    {"ssl3", OPT_SSL3, '-', "Just talk SSLv3"},
#endif
#ifndef OPENSSL_NO_TLS1
    {"tls1", OPT_TLS1, '-', "Just talk TLSv1"},
#endif
#ifndef OPENSSL_NO_TLS1_1
    {"tls1_1", OPT_TLS1_1, '-', "Just talk TLSv1.1"},
#endif
#ifndef OPENSSL_NO_TLS1_2
    {"tls1_2", OPT_TLS1_2, '-', "just talk TLSv1.2"},
#endif
#ifndef OPENSSL_NO_DTLS
    {"dtls", OPT_DTLS, '-'},
    {"dtls1", OPT_DTLS1, '-', "Just talk DTLSv1"},
    {"dtls1_2", OPT_DTLS1_2, '-', "Just talk DTLSv1.2"},
    {"timeout", OPT_TIMEOUT, '-', "Enable timeouts"},
    {"mtu", OPT_MTU, 'p', "Set link layer MTU"},
    {"chain", OPT_CHAIN, '-', "Read a certificate chain"},
    {"listen", OPT_LISTEN, '-',
     "Listen for a DTLS ClientHello with a cookie and then connect"},
#endif
#ifndef OPENSSL_NO_DTLS1
    {"dtls1", OPT_DTLS1, '-', "Just talk DTLSv1"},
#endif
#ifndef OPENSSL_NO_DTLS1_2
    {"dtls1_2", OPT_DTLS1_2, '-', "Just talk DTLSv1.2"},
#endif
#ifndef OPENSSL_NO_DH
    {"no_dhe", OPT_NO_DHE, '-', "Disable ephemeral DH"},
#endif
@@ -1039,19 +1049,6 @@ int s_server_main(int argc, char *argv[])
    prog = opt_init(argc, argv, s_server_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
#ifdef OPENSSL_NO_PSK
        case OPT_PSK_HINT:
        case OPT_PSK:
#endif
#ifdef OPENSSL_NO_DTLS
        case OPT_DTLS:
        case OPT_DTLS1:
        case OPT_DTLS1_2:
        case OPT_TIMEOUT:
        case OPT_MTU:
        case OPT_CHAIN:
        case OPT_LISTEN:
#endif
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
@@ -1299,33 +1296,33 @@ int s_server_main(int argc, char *argv[])
        case OPT_NO_RESUME_EPHEMERAL:
            no_resume_ephemeral = 1;
            break;
#ifndef OPENSSL_NO_PSK
        case OPT_PSK_HINT:
#ifndef OPENSSL_NO_PSK
            psk_identity_hint = opt_arg();
#endif
            break;
        case OPT_PSK:
#ifndef OPENSSL_NO_PSK
            for (p = psk_key = opt_arg(); *p; p++) {
                if (isxdigit(*p))
                    continue;
                BIO_printf(bio_err, "Not a hex number '%s'\n", *argv);
                goto end;
            }
            break;
#endif
#ifndef OPENSSL_NO_SRP
            break;
        case OPT_SRPVFILE:
#ifndef OPENSSL_NO_SRP
            srp_verifier_file = opt_arg();
            meth = TLSv1_server_method();
#endif
            break;
        case OPT_SRPUSERSEED:
#ifndef OPENSSL_NO_SRP
            srpuserseed = opt_arg();
            meth = TLSv1_server_method();
            break;
#else
        case OPT_SRPVFILE:
        case OPT_SRPUSERSEED:
            break;
#endif
            break;
        case OPT_REV:
            rev = 1;
            break;
@@ -1347,40 +1344,58 @@ int s_server_main(int argc, char *argv[])
#endif
            break;
        case OPT_TLS1_2:
#ifndef OPENSSL_NO_TLS1_2
            meth = TLSv1_2_server_method();
#endif
            break;
        case OPT_TLS1_1:
#ifndef OPENSSL_NO_TLS1_1
            meth = TLSv1_1_server_method();
#endif
            break;
        case OPT_TLS1:
#ifndef OPENSSL_NO_TLS1
            meth = TLSv1_server_method();
#endif
            break;
#ifndef OPENSSL_NO_DTLS
        case OPT_DTLS:
#ifndef OPENSSL_NO_DTLS
            meth = DTLS_server_method();
            socket_type = SOCK_DGRAM;
#endif
            break;
        case OPT_DTLS1:
#ifndef OPENSSL_NO_DTLS1
            meth = DTLSv1_server_method();
            socket_type = SOCK_DGRAM;
#endif
            break;
        case OPT_DTLS1_2:
#ifndef OPENSSL_NO_DTLS1_2
            meth = DTLSv1_2_server_method();
            socket_type = SOCK_DGRAM;
#endif
            break;
        case OPT_TIMEOUT:
#ifndef OPENSSL_NO_DTLS
            enable_timeouts = 1;
#endif
            break;
        case OPT_MTU:
#ifndef OPENSSL_NO_DTLS
            socket_mtu = atol(opt_arg());
#endif
            break;
        case OPT_CHAIN:
#ifndef OPENSSL_NO_DTLS
            cert_chain = 1;
#endif
            break;
        case OPT_LISTEN:
#ifndef OPENSSL_NO_DTLS
            dtlslisten = 1;
            break;
#endif
            break;
        case OPT_ID_PREFIX:
            session_id_prefix = opt_arg();
            break;
Loading