tls: ban SSL3, TLS1, TLS1.1 and DTLS1.0 at security level one and above

This is in line with the NEWS entry (erroneously) announcing such for 3.0.

Fixes #18194

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/18236)
diff --git a/NEWS.md b/NEWS.md
index 6f741ee..8dc94bc 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -25,6 +25,7 @@
     by default.
   * TCP Fast Open (RFC7413) support is available on Linux, macOS, and FreeBSD
     where enabled and supported.
+  * SSL 3, TLS 1.0, TLS 1.1, and DTLS 1.0 only work at security level 0.
 
 OpenSSL 3.0
 -----------
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index e8c11ea..267e869 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -1047,18 +1047,12 @@
         }
     case SSL_SECOP_VERSION:
         if (!SSL_IS_DTLS(s)) {
-            /* SSLv3 not allowed at level 2 */
-            if (nid <= SSL3_VERSION && level >= 2)
-                return 0;
-            /* TLS v1.1 and above only for level 3 */
-            if (nid <= TLS1_VERSION && level >= 3)
-                return 0;
-            /* TLS v1.2 only for level 4 and above */
-            if (nid <= TLS1_1_VERSION && level >= 4)
+            /* SSLv3, TLS v1.0 and TLS v1.1 only allowed at level 0 */
+            if (nid <= TLS1_1_VERSION && level > 0)
                 return 0;
         } else {
-            /* DTLS v1.2 only for level 4 and above */
-            if (DTLS_VERSION_LT(nid, DTLS1_2_VERSION) && level >= 4)
+            /* DTLS v1.0 only allowed at level 0 */
+            if (DTLS_VERSION_LT(nid, DTLS1_2_VERSION) && level > 0)
                 return 0;
         }
         break;
diff --git a/test/bad_dtls_test.c b/test/bad_dtls_test.c
index f8c6b14..8849269 100644
--- a/test/bad_dtls_test.c
+++ b/test/bad_dtls_test.c
@@ -499,6 +499,7 @@
             || !TEST_true(SSL_CTX_set_cipher_list(ctx, "AES128-SHA")))
         goto end;
 
+    SSL_CTX_set_security_level(ctx, 0);
     con = SSL_new(ctx);
     if (!TEST_ptr(con)
             || !TEST_true(SSL_set_session(con, sess)))
diff --git a/test/recipes/80-test_ssl_old.t b/test/recipes/80-test_ssl_old.t
index 8c52b63..50b74a1 100644
--- a/test/recipes/80-test_ssl_old.t
+++ b/test/recipes/80-test_ssl_old.t
@@ -78,9 +78,10 @@
 # If you're adding tests here, you probably want to convert them to the
 # new format in ssl_test.c and add recipes to 80-test_ssl_new.t instead.
 plan tests =>
-   ($no_fips ? 0 : 5)     # testssl with fips provider
+   ($no_fips ? 0 : 6)     # testssl with fips provider
     + 1                   # For testss
     + 5                   # For the testssl with default provider
+    + 1                   # For security level 0 failure tests
     ;
 
 subtest 'test_ss' => sub {
@@ -345,7 +346,6 @@
         $dsa_cert = 1;
     }
 
-
     subtest 'standard SSL tests' => sub {
         ######################################################################
         plan tests => 19;
@@ -527,6 +527,44 @@
         }
     };
 
+    subtest 'SSL security level failure tests' => sub {
+        ######################################################################
+        plan tests => 3;
+
+      SKIP: {
+          skip "SSLv3 is not supported by this OpenSSL build", 1
+              if disabled("ssl3");
+
+          skip "SSLv3 is not supported by the FIPS provider", 1
+              if $provider eq "fips";
+
+          is(run(test([@ssltest, "-bio_pair", "-ssl3", "-cipher", '@SECLEVEL=1'])),
+             0, "test sslv3 fails at security level 1, expecting failure");
+        }
+
+      SKIP: {
+          skip "TLSv1.0 is not supported by this OpenSSL build", 1
+              if $no_tls1;
+
+          skip "TLSv1.0 is not supported by the FIPS provider", 1
+              if $provider eq "fips";
+
+          is(run(test([@ssltest, "-bio_pair", "-tls1", "-cipher", '@SECLEVEL=1'])),
+             0, 'test tls1 fails at security level 1, expecting failure');
+        }
+
+      SKIP: {
+          skip "TLSv1.1 is not supported by this OpenSSL build", 1
+              if $no_tls1_1;
+
+          skip "TLSv1.1 is not supported by the FIPS provider", 1
+              if $provider eq "fips";
+
+          is(run(test([@ssltest, "-bio_pair", "-tls1_1", "-cipher", '@SECLEVEL=1'])),
+             0, 'test tls1.1 fails at security level 1, expecting failure');
+        }
+    };
+
     subtest 'RSA/(EC)DHE/PSK tests' => sub {
         ######################################################################
 
@@ -579,14 +617,14 @@
 	}
 
       SKIP: {
-            skip "TLSv1.1 is not supported by this OpenSSL build", 4
-                if $no_tls1_1;
+            skip "TLSv1.2 is not supported by this OpenSSL build", 4
+                if $no_tls1_2;
 
         SKIP: {
             skip "skipping auto DHE PSK test at SECLEVEL 3", 1
                 if ($no_dh || $no_psk);
 
-            ok(run(test(['ssl_old_test', '-tls1_1', '-dhe4096', '-psk', '0102030405', '-cipher', '@SECLEVEL=3:DHE-PSK-AES256-CBC-SHA384'])),
+            ok(run(test(['ssl_old_test', '-tls1_2', '-dhe4096', '-psk', '0102030405', '-cipher', '@SECLEVEL=3:DHE-PSK-AES256-CBC-SHA384'])),
                'test auto DHE PSK meets security strength');
           }
 
@@ -594,7 +632,7 @@
             skip "skipping auto ECDHE PSK test at SECLEVEL 3", 1
                 if ($no_ec || $no_psk);
 
-            ok(run(test(['ssl_old_test', '-tls1_1', '-no_dhe', '-psk', '0102030405', '-cipher', '@SECLEVEL=3:ECDHE-PSK-AES256-CBC-SHA384'])),
+            ok(run(test(['ssl_old_test', '-tls1_2', '-no_dhe', '-psk', '0102030405', '-cipher', '@SECLEVEL=3:ECDHE-PSK-AES256-CBC-SHA384'])),
                'test auto ECDHE PSK meets security strength');
           }
 
@@ -602,7 +640,7 @@
             skip "skipping no RSA PSK at SECLEVEL 3 test", 1
                 if ($no_rsa || $no_psk);
 
-            ok(!run(test(['ssl_old_test', '-tls1_1', '-no_dhe', '-psk', '0102030405', '-cipher', '@SECLEVEL=3:RSA-PSK-AES256-CBC-SHA384'])),
+            ok(!run(test(['ssl_old_test', '-tls1_2', '-no_dhe', '-psk', '0102030405', '-cipher', '@SECLEVEL=3:RSA-PSK-AES256-CBC-SHA384'])),
                'test auto RSA PSK does not meet security level 3 requirements (PFS)');
           }
 
@@ -610,7 +648,7 @@
             skip "skipping no PSK at SECLEVEL 3 test", 1
                 if ($no_psk);
 
-            ok(!run(test(['ssl_old_test', '-tls1_1', '-no_dhe', '-psk', '0102030405', '-cipher', '@SECLEVEL=3:PSK-AES256-CBC-SHA384'])),
+            ok(!run(test(['ssl_old_test', '-tls1_2', '-no_dhe', '-psk', '0102030405', '-cipher', '@SECLEVEL=3:PSK-AES256-CBC-SHA384'])),
                'test auto PSK does not meet security level 3 requirements (PFS)');
           }
 	}
diff --git a/test/ssl-tests/20-cert-select.cnf b/test/ssl-tests/20-cert-select.cnf
index 853deff..5cb7aca 100644
--- a/test/ssl-tests/20-cert-select.cnf
+++ b/test/ssl-tests/20-cert-select.cnf
@@ -1119,11 +1119,11 @@
 
 [34-Only RSA-PSS Certificate, TLS v1.1-server]
 Certificate = ${ENV::TEST_CERTS_DIR}/server-pss-cert.pem
-CipherString = DEFAULT
+CipherString = DEFAULT:@SECLEVEL=0
 PrivateKey = ${ENV::TEST_CERTS_DIR}/server-pss-key.pem
 
 [34-Only RSA-PSS Certificate, TLS v1.1-client]
-CipherString = DEFAULT
+CipherString = DEFAULT:@SECLEVEL=0
 MaxProtocol = TLSv1.1
 VerifyCAFile = ${ENV::TEST_CERTS_DIR}/rootcert.pem
 VerifyMode = Peer
diff --git a/test/ssl-tests/20-cert-select.cnf.in b/test/ssl-tests/20-cert-select.cnf.in
index 26c7318..d0cc5cf 100644
--- a/test/ssl-tests/20-cert-select.cnf.in
+++ b/test/ssl-tests/20-cert-select.cnf.in
@@ -585,9 +585,14 @@
 my @tests_tls_1_1 = (
     {
         name => "Only RSA-PSS Certificate, TLS v1.1",
-        server => $server_pss_only,
+        server => {
+            "CipherString" => "DEFAULT:\@SECLEVEL=0",
+            "Certificate" => test_pem("server-pss-cert.pem"),
+            "PrivateKey" => test_pem("server-pss-key.pem"),
+        },
         client => {
             "MaxProtocol" => "TLSv1.1",
+            "CipherString" => "DEFAULT:\@SECLEVEL=0",
         },
         test   => {
             "ExpectedResult" => "ServerFail"