init
This commit is contained in:
1117
test/org/apache/tomcat/util/net/openssl/ciphers/TestCipher.java
Normal file
1117
test/org/apache/tomcat/util/net/openssl/ciphers/TestCipher.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,620 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.tomcat.util.net.openssl.ciphers;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
public class TestOpenSSLCipherConfigurationParser {
|
||||
|
||||
@Test
|
||||
public void testDEFAULT() throws Exception {
|
||||
if (TesterOpenSSL.VERSION < 10100) {
|
||||
// Account for classes of ciphers removed from DEFAULT in 1.1.0
|
||||
testSpecification("DEFAULT:!RC4:!DSS:!SEED:!IDEA:!CAMELLIA:!AESCCM:!3DES");
|
||||
} else {
|
||||
testSpecification("DEFAULT");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCOMPLEMENTOFDEFAULT() throws Exception {
|
||||
if (TesterOpenSSL.VERSION < 10100) {
|
||||
// Account for classes of ciphers removed from DEFAULT in 1.1.0
|
||||
testSpecification("COMPLEMENTOFDEFAULT:RC4:DSS:SEED:IDEA:CAMELLIA:AESCCM:aNULL:3DES");
|
||||
} else {
|
||||
testSpecification("COMPLEMENTOFDEFAULT");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testALL() throws Exception {
|
||||
testSpecification("ALL");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCOMPLEMENTOFALL() throws Exception {
|
||||
testSpecification("COMPLEMENTOFALL");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testaNULL() throws Exception {
|
||||
testSpecification("aNULL");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testeNULL() throws Exception {
|
||||
testSpecification("eNULL");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testHIGH() throws Exception {
|
||||
testSpecification("HIGH");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMEDIUM() throws Exception {
|
||||
testSpecification("MEDIUM");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testLOW() throws Exception {
|
||||
testSpecification("LOW");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testEXPORT40() throws Exception {
|
||||
testSpecification("EXPORT40");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testEXPORT() throws Exception {
|
||||
testSpecification("EXPORT");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRSA() throws Exception {
|
||||
testSpecification("RSA");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testaRSA() throws Exception {
|
||||
testSpecification("aRSA");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testkRSA() throws Exception {
|
||||
testSpecification("kRSA");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testkEDH() throws Exception {
|
||||
testSpecification("kEDH");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testkDHE() throws Exception {
|
||||
// This alias was introduced in 1.0.2
|
||||
if (TesterOpenSSL.VERSION >= 10002) {
|
||||
testSpecification("kDHE");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testEDH() throws Exception {
|
||||
testSpecification("EDH");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDHE() throws Exception {
|
||||
// This alias was introduced in 1.0.2
|
||||
if (TesterOpenSSL.VERSION >= 10002) {
|
||||
testSpecification("DHE");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testkDHr() throws Exception {
|
||||
testSpecification("kDHr");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testkDHd() throws Exception {
|
||||
testSpecification("kDHd");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testkDH() throws Exception {
|
||||
testSpecification("kDH");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testkECDHr() throws Exception {
|
||||
testSpecification("kECDHr");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testkECDHe() throws Exception {
|
||||
testSpecification("kECDHe");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testkECDH() throws Exception {
|
||||
testSpecification("kECDH");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testkEECDH() throws Exception {
|
||||
testSpecification("kEECDH");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testECDH() throws Exception {
|
||||
testSpecification("ECDH");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testkECDHE() throws Exception {
|
||||
testSpecification("kECDHE");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testECDHE() throws Exception {
|
||||
testSpecification("ECDHE");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore("Contrary to the docs, OpenSSL does not recognise EECDHE")
|
||||
public void testEECDHE() throws Exception {
|
||||
testSpecification("EECDHE");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAECDH() throws Exception {
|
||||
testSpecification("AECDH");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDSS() throws Exception {
|
||||
testSpecification("DSS");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testaDSS() throws Exception {
|
||||
testSpecification("aDSS");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testaDH() throws Exception {
|
||||
testSpecification("aDH");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testaECDH() throws Exception {
|
||||
testSpecification("aECDH");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testaECDSA() throws Exception {
|
||||
testSpecification("aECDSA");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testECDSA() throws Exception {
|
||||
testSpecification("ECDSA");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testkFZA() throws Exception {
|
||||
testSpecification("kFZA");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testaFZA() throws Exception {
|
||||
testSpecification("aFZA");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testeFZA() throws Exception {
|
||||
testSpecification("eFZA");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testFZA() throws Exception {
|
||||
testSpecification("FZA");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testTLSv1_2() throws Exception {
|
||||
testSpecification("TLSv1.2");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testTLSv1() throws Exception {
|
||||
// In OpenSSL 1.1.0-dev, TLSv1 refers to those ciphers that require
|
||||
// TLSv1 rather than being an alias for SSLv3
|
||||
if (TesterOpenSSL.VERSION >= 10100) {
|
||||
testSpecification("TLSv1");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSSLv2() throws Exception {
|
||||
testSpecification("SSLv2");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSSLv3() throws Exception {
|
||||
// In OpenSSL 1.1.0-dev, TLSv1 refers to those ciphers that require
|
||||
// TLSv1 rather than being an alias for SSLv3
|
||||
if (TesterOpenSSL.VERSION < 10100) {
|
||||
testSpecification("SSLv3:TLSv1");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDH() throws Exception {
|
||||
testSpecification("DH");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testADH() throws Exception {
|
||||
testSpecification("ADH");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAES128() throws Exception {
|
||||
testSpecification("AES128");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAES256() throws Exception {
|
||||
testSpecification("AES256");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAES() throws Exception {
|
||||
testSpecification("AES");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAESGCM() throws Exception {
|
||||
testSpecification("AESGCM");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAESCCM() throws Exception {
|
||||
testSpecification("AESCCM");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAESCCM8() throws Exception {
|
||||
testSpecification("AESCCM8");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCAMELLIA128() throws Exception {
|
||||
testSpecification("CAMELLIA128");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCAMELLIA256() throws Exception {
|
||||
testSpecification("CAMELLIA256");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCAMELLIA() throws Exception {
|
||||
testSpecification("CAMELLIA");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCHACHA20() throws Exception {
|
||||
testSpecification("CHACHA20");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void test3DES() throws Exception {
|
||||
testSpecification("3DES");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDES() throws Exception {
|
||||
testSpecification("DES");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRC4() throws Exception {
|
||||
testSpecification("RC4");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRC2() throws Exception {
|
||||
testSpecification("RC2");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testIDEA() throws Exception {
|
||||
testSpecification("IDEA");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSEED() throws Exception {
|
||||
testSpecification("SEED");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMD5() throws Exception {
|
||||
testSpecification("MD5");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSHA1() throws Exception {
|
||||
testSpecification("SHA1");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSHA() throws Exception {
|
||||
testSpecification("SHA");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSHA256() throws Exception {
|
||||
testSpecification("SHA256");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSHA384() throws Exception {
|
||||
testSpecification("SHA384");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testKRB5() throws Exception {
|
||||
testSpecification("KRB5");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testaGOST() throws Exception {
|
||||
testSpecification("aGOST");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testaGOST01() throws Exception {
|
||||
testSpecification("aGOST01");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testaGOST94() throws Exception {
|
||||
testSpecification("aGOST94");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testkGOST() throws Exception {
|
||||
testSpecification("kGOST");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGOST94() throws Exception {
|
||||
testSpecification("GOST94");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGOST89MAC() throws Exception {
|
||||
testSpecification("GOST89MAC");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testaPSK() throws Exception {
|
||||
testSpecification("aPSK");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testkPSK() throws Exception {
|
||||
testSpecification("kPSK");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testkRSAPSK() throws Exception {
|
||||
testSpecification("kRSAPSK");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testkECDHEPSK() throws Exception {
|
||||
testSpecification("kECDHEPSK");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testkDHEPSK() throws Exception {
|
||||
testSpecification("kDHEPSK");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testPSK() throws Exception {
|
||||
testSpecification("PSK");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testARIA() throws Exception {
|
||||
testSpecification("ARIA");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testARIA128() throws Exception {
|
||||
testSpecification("ARIA128");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testARIA256() throws Exception {
|
||||
testSpecification("ARIA256");
|
||||
}
|
||||
|
||||
|
||||
// TODO: Add tests for the individual operators
|
||||
|
||||
@Test
|
||||
public void testSpecification01() throws Exception {
|
||||
// Tomcat 8 default as of 2014-08-04
|
||||
// This gets an A- from https://www.ssllabs.com/ssltest with no FS for
|
||||
// a number of the reference browsers
|
||||
testSpecification("HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSpecification02() throws Exception {
|
||||
// Suggestion from dev list (s/ECDHE/kEECDH/, s/DHE/EDH/
|
||||
testSpecification("!aNULL:!eNULL:!EXPORT:!DSS:!DES:!SSLv2:kEECDH:ECDH:EDH:AES256-GCM-SHA384:AES128-GCM-SHA256:+RC4:HIGH:aRSA:kECDHr:MEDIUM");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSpecification03() throws Exception {
|
||||
// Reported as failing during 8.0.11 release vote by Ognjen Blagojevic
|
||||
// EDH was introduced in 1.0.0
|
||||
testSpecification("EECDH+aRSA+SHA384:EECDH:EDH+aRSA:RC4:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS");
|
||||
}
|
||||
|
||||
private void testSpecification(String specification) throws Exception {
|
||||
// Filter out cipher suites that OpenSSL does not implement
|
||||
String openSSLCipherList = TesterOpenSSL.getOpenSSLCiphersAsExpression(specification);
|
||||
List<String> jsseCipherListFromOpenSSL =
|
||||
OpenSSLCipherConfigurationParser.parseExpression(openSSLCipherList);
|
||||
List<String> jsseCipherListFromParser =
|
||||
OpenSSLCipherConfigurationParser.parseExpression(specification);
|
||||
|
||||
TesterOpenSSL.removeUnimplementedCiphersJsse(jsseCipherListFromParser);
|
||||
|
||||
// First check the lists have the same entries
|
||||
// Order is NOT important at this point. It is checked below.
|
||||
Assert.assertEquals(
|
||||
"Expected " + jsseCipherListFromParser.size() + " ciphers but got "
|
||||
+ jsseCipherListFromOpenSSL.size() + " for the specification '"
|
||||
+ specification + "'",
|
||||
new TreeSet<>(jsseCipherListFromParser), new TreeSet<>(jsseCipherListFromOpenSSL));
|
||||
|
||||
// OpenSSL treats many ciphers as having equal preference. The order
|
||||
// returned depends on the order they are requested. The following code
|
||||
// checks that the Parser produces a cipher list that is consistent with
|
||||
// OpenSSL's preference order by confirming that running through OpenSSL
|
||||
// does not change the order.
|
||||
String parserOrderedExpression = listToString(jsseCipherListFromParser, ',');
|
||||
Assert.assertEquals(
|
||||
listToString(OpenSSLCipherConfigurationParser.parseExpression(
|
||||
parserOrderedExpression), ','),
|
||||
parserOrderedExpression);
|
||||
}
|
||||
|
||||
|
||||
private String listToString(List<String> list, char separator) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
boolean first = true;
|
||||
for (String entry : list) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
sb.append(separator);
|
||||
}
|
||||
sb.append(entry);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.tomcat.util.net.openssl.ciphers;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
/*
|
||||
* The unit test is independent of OpenSSL version and does not require OpenSSL
|
||||
* to be present.
|
||||
*/
|
||||
public class TestOpenSSLCipherConfigurationParserOnly {
|
||||
|
||||
@Test
|
||||
public void testDefaultSort01() throws Exception {
|
||||
// Reproducing a failure observed on Gump with OpenSSL 1.1.x
|
||||
|
||||
// Everything else being equal, AES is preferred
|
||||
LinkedHashSet<Cipher> input = new LinkedHashSet<>();
|
||||
input.add(Cipher.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384);
|
||||
input.add(Cipher.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384);
|
||||
input.add(Cipher.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384);
|
||||
input.add(Cipher.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384);
|
||||
LinkedHashSet<Cipher> result = OpenSSLCipherConfigurationParser.defaultSort(input);
|
||||
|
||||
LinkedHashSet<Cipher> expected = new LinkedHashSet<>();
|
||||
expected.add(Cipher.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384);
|
||||
expected.add(Cipher.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384);
|
||||
expected.add(Cipher.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384);
|
||||
expected.add(Cipher.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384);
|
||||
|
||||
Assert.assertEquals(expected.toString(), result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultSort02() throws Exception {
|
||||
// Reproducing a failure observed on Gump with OpenSSL 1.1.x
|
||||
|
||||
// ECHDE should beat AES
|
||||
LinkedHashSet<Cipher> input = new LinkedHashSet<>();
|
||||
input.add(Cipher.TLS_RSA_WITH_AES_256_CBC_SHA);
|
||||
input.add(Cipher.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384);
|
||||
LinkedHashSet<Cipher> result = OpenSSLCipherConfigurationParser.defaultSort(input);
|
||||
|
||||
LinkedHashSet<Cipher> expected = new LinkedHashSet<>();
|
||||
expected.add(Cipher.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384);
|
||||
expected.add(Cipher.TLS_RSA_WITH_AES_256_CBC_SHA);
|
||||
|
||||
Assert.assertEquals(expected.toString(), result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultSort03() throws Exception {
|
||||
// Reproducing a failure observed on Gump with OpenSSL 1.1.x
|
||||
|
||||
// AES should beat CAMELLIA
|
||||
LinkedHashSet<Cipher> input = new LinkedHashSet<>();
|
||||
input.add(Cipher.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384);
|
||||
input.add(Cipher.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384);
|
||||
LinkedHashSet<Cipher> result = OpenSSLCipherConfigurationParser.defaultSort(input);
|
||||
|
||||
LinkedHashSet<Cipher> expected = new LinkedHashSet<>();
|
||||
expected.add(Cipher.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384);
|
||||
expected.add(Cipher.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384);
|
||||
|
||||
Assert.assertEquals(expected.toString(), result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRename01() throws Exception {
|
||||
// EDH -> DHE
|
||||
LinkedHashSet<Cipher> result =
|
||||
OpenSSLCipherConfigurationParser.parse("EXP-EDH-DSS-DES-CBC-SHA");
|
||||
LinkedHashSet<Cipher> expected = new LinkedHashSet<>();
|
||||
expected.add(Cipher.TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA);
|
||||
|
||||
Assert.assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomOrdering() throws Exception {
|
||||
// https://bz.apache.org/bugzilla/show_bug.cgi?id=59081
|
||||
LinkedHashSet<Cipher> result = OpenSSLCipherConfigurationParser.parse(
|
||||
"ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:" +
|
||||
"DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DES-CBC3-SHA");
|
||||
LinkedHashSet<Cipher> expected = new LinkedHashSet<>();
|
||||
expected.add(Cipher.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384);
|
||||
expected.add(Cipher.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA);
|
||||
expected.add(Cipher.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA);
|
||||
expected.add(Cipher.TLS_DHE_RSA_WITH_AES_256_CBC_SHA);
|
||||
expected.add(Cipher.TLS_DHE_RSA_WITH_AES_128_CBC_SHA);
|
||||
expected.add(Cipher.TLS_RSA_WITH_3DES_EDE_CBC_SHA);
|
||||
|
||||
Assert.assertEquals(expected.toString(), result.toString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,527 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.apache.tomcat.util.net.openssl.ciphers;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.catalina.util.IOTools;
|
||||
|
||||
public class TesterOpenSSL {
|
||||
|
||||
public static final int VERSION;
|
||||
|
||||
public static final Set<Cipher> OPENSSL_UNIMPLEMENTED_CIPHERS;
|
||||
|
||||
public static final Map<String,String> OPENSSL_RENAMED_CIPHERS;
|
||||
|
||||
static {
|
||||
// Note: The following lists are intended to be aligned with the most
|
||||
// recent release of each OpenSSL release branch. Running the unit
|
||||
// tests with earlier releases is likely to result in failures.
|
||||
|
||||
String versionString = null;
|
||||
try {
|
||||
versionString = executeOpenSSLCommand("version");
|
||||
} catch (IOException e) {
|
||||
versionString = "";
|
||||
}
|
||||
if (versionString.startsWith("OpenSSL 3.0.0")) {
|
||||
// Note: Gump currently tests 9.0.x with OpenSSL master
|
||||
// (a.k.a 3.0.0-dev)
|
||||
VERSION = 30000;
|
||||
} else if (versionString.startsWith("OpenSSL 1.1.1")) {
|
||||
// LTS
|
||||
// Supported until at least 2023-09-11
|
||||
VERSION = 10101;
|
||||
} else if (versionString.startsWith("OpenSSL 1.1.0")) {
|
||||
// Support ends 2019-09-11
|
||||
VERSION = 10100;
|
||||
} else if (versionString.startsWith("OpenSSL 1.0.2")) {
|
||||
// LTS
|
||||
// Support ends 2019-12-31
|
||||
// Note: Gump current tests 8.5.x with OpenSSL 1.0.2
|
||||
VERSION = 10002;
|
||||
// Note: Release branches 1.0.1 and earlier are no longer supported by
|
||||
// the OpenSSL team so these tests don't support them either.
|
||||
} else {
|
||||
VERSION = -1;
|
||||
}
|
||||
|
||||
HashSet<Cipher> unimplemented = new HashSet<>();
|
||||
|
||||
// These have been removed from all supported versions.
|
||||
unimplemented.add(Cipher.TLS_DHE_DSS_WITH_RC4_128_SHA);
|
||||
unimplemented.add(Cipher.TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5);
|
||||
unimplemented.add(Cipher.TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA);
|
||||
unimplemented.add(Cipher.TLS_RSA_EXPORT1024_WITH_RC4_56_SHA);
|
||||
unimplemented.add(Cipher.TLS_RSA_EXPORT1024_WITH_RC4_56_MD5);
|
||||
unimplemented.add(Cipher.TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_DH_anon_WITH_DES_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_DH_anon_EXPORT_WITH_RC4_40_MD5);
|
||||
unimplemented.add(Cipher.TLS_DHE_RSA_WITH_DES_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_DHE_DSS_WITH_DES_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_DH_RSA_WITH_DES_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_DH_DSS_WITH_DES_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_RSA_WITH_DES_CBC_SHA);
|
||||
unimplemented.add(Cipher.SSL2_DES_64_CBC_WITH_MD5);
|
||||
unimplemented.add(Cipher.TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_RSA_EXPORT_WITH_DES40_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5);
|
||||
unimplemented.add(Cipher.TLS_RSA_EXPORT_WITH_RC4_40_MD5);
|
||||
unimplemented.add(Cipher.SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5);
|
||||
unimplemented.add(Cipher.SSL_CK_RC2_128_CBC_WITH_MD5);
|
||||
unimplemented.add(Cipher.SSL_CK_RC4_128_WITH_MD5);
|
||||
unimplemented.add(Cipher.SSL2_RC4_128_EXPORT40_WITH_MD5);
|
||||
unimplemented.add(Cipher.SSL2_IDEA_128_CBC_WITH_MD5);
|
||||
unimplemented.add(Cipher.SSL2_DES_192_EDE3_CBC_WITH_MD5);
|
||||
|
||||
// These are TLS v1.3 cipher suites
|
||||
// Java does not currently support these so they are excluded from the
|
||||
// testing.
|
||||
// Note: If OpenSSL is used then some of these may be available
|
||||
// depending on the OpenSSL version used and the defaults for that
|
||||
// version
|
||||
unimplemented.add(Cipher.TLS_AES_128_CCM_8_SHA256);
|
||||
unimplemented.add(Cipher.TLS_AES_128_CCM_SHA256);
|
||||
unimplemented.add(Cipher.TLS_AES_128_GCM_SHA256);
|
||||
unimplemented.add(Cipher.TLS_AES_256_GCM_SHA384);
|
||||
unimplemented.add(Cipher.TLS_CHACHA20_POLY1305_SHA256);
|
||||
|
||||
if (VERSION < 10100) {
|
||||
// These were implemented in 1.1.0 so won't be available in any
|
||||
// earlier version
|
||||
unimplemented.add(Cipher.TLS_PSK_WITH_NULL_SHA);
|
||||
unimplemented.add(Cipher.TLS_DHE_PSK_WITH_NULL_SHA);
|
||||
unimplemented.add(Cipher.TLS_RSA_PSK_WITH_NULL_SHA);
|
||||
unimplemented.add(Cipher.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256);
|
||||
unimplemented.add(Cipher.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384);
|
||||
unimplemented.add(Cipher.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256);
|
||||
unimplemented.add(Cipher.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384);
|
||||
unimplemented.add(Cipher.TLS_PSK_WITH_AES_128_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_PSK_WITH_AES_256_CBC_SHA384);
|
||||
unimplemented.add(Cipher.TLS_PSK_WITH_NULL_SHA256);
|
||||
unimplemented.add(Cipher.TLS_PSK_WITH_NULL_SHA384);
|
||||
unimplemented.add(Cipher.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384);
|
||||
unimplemented.add(Cipher.TLS_DHE_PSK_WITH_NULL_SHA256);
|
||||
unimplemented.add(Cipher.TLS_DHE_PSK_WITH_NULL_SHA384);
|
||||
unimplemented.add(Cipher.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384);
|
||||
unimplemented.add(Cipher.TLS_RSA_PSK_WITH_NULL_SHA256);
|
||||
unimplemented.add(Cipher.TLS_RSA_PSK_WITH_NULL_SHA384);
|
||||
unimplemented.add(Cipher.TLS_DHE_PSK_WITH_RC4_128_SHA);
|
||||
unimplemented.add(Cipher.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_DHE_PSK_WITH_AES_128_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_DHE_PSK_WITH_AES_256_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_RSA_PSK_WITH_RC4_128_SHA);
|
||||
unimplemented.add(Cipher.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_RSA_PSK_WITH_AES_128_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_RSA_PSK_WITH_AES_256_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_PSK_WITH_RC4_128_SHA);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_PSK_WITH_NULL_SHA);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_PSK_WITH_NULL_SHA256);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_PSK_WITH_NULL_SHA384);
|
||||
unimplemented.add(Cipher.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384);
|
||||
unimplemented.add(Cipher.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384);
|
||||
unimplemented.add(Cipher.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384);
|
||||
unimplemented.add(Cipher.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384);
|
||||
unimplemented.add(Cipher.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384);
|
||||
unimplemented.add(Cipher.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384);
|
||||
unimplemented.add(Cipher.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_PSK_WITH_AES_128_GCM_SHA256);
|
||||
unimplemented.add(Cipher.TLS_PSK_WITH_AES_256_GCM_SHA384);
|
||||
unimplemented.add(Cipher.TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_RSA_WITH_AES_128_CCM);
|
||||
unimplemented.add(Cipher.TLS_RSA_WITH_AES_256_CCM);
|
||||
unimplemented.add(Cipher.TLS_DHE_RSA_WITH_AES_128_CCM);
|
||||
unimplemented.add(Cipher.TLS_DHE_RSA_WITH_AES_256_CCM);
|
||||
unimplemented.add(Cipher.TLS_RSA_WITH_AES_128_CCM_8);
|
||||
unimplemented.add(Cipher.TLS_RSA_WITH_AES_256_CCM_8);
|
||||
unimplemented.add(Cipher.TLS_DHE_RSA_WITH_AES_128_CCM_8);
|
||||
unimplemented.add(Cipher.TLS_DHE_RSA_WITH_AES_256_CCM_8);
|
||||
unimplemented.add(Cipher.TLS_PSK_WITH_AES_128_CCM);
|
||||
unimplemented.add(Cipher.TLS_PSK_WITH_AES_256_CCM);
|
||||
unimplemented.add(Cipher.TLS_DHE_PSK_WITH_AES_128_CCM);
|
||||
unimplemented.add(Cipher.TLS_DHE_PSK_WITH_AES_256_CCM);
|
||||
unimplemented.add(Cipher.TLS_PSK_WITH_AES_128_CCM_8);
|
||||
unimplemented.add(Cipher.TLS_PSK_WITH_AES_256_CCM_8);
|
||||
unimplemented.add(Cipher.TLS_PSK_DHE_WITH_AES_128_CCM_8);
|
||||
unimplemented.add(Cipher.TLS_PSK_DHE_WITH_AES_256_CCM_8);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_ECDSA_WITH_AES_128_CCM);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_ECDSA_WITH_AES_256_CCM);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256);
|
||||
unimplemented.add(Cipher.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256);
|
||||
unimplemented.add(Cipher.TLS_PSK_WITH_CHACHA20_POLY1305_SHA256);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256);
|
||||
unimplemented.add(Cipher.TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256);
|
||||
unimplemented.add(Cipher.TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256);
|
||||
} else {
|
||||
// These were removed in 1.1.0 so won't be available from that
|
||||
// version onwards.
|
||||
unimplemented.add(Cipher.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_DH_DSS_WITH_AES_128_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_DH_DSS_WITH_AES_128_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_DH_DSS_WITH_AES_128_GCM_SHA256);
|
||||
unimplemented.add(Cipher.TLS_DH_DSS_WITH_AES_256_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_DH_DSS_WITH_AES_256_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_DH_DSS_WITH_AES_256_GCM_SHA384);
|
||||
unimplemented.add(Cipher.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_DH_DSS_WITH_SEED_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_DH_RSA_WITH_AES_128_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_DH_RSA_WITH_AES_128_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_DH_RSA_WITH_AES_128_GCM_SHA256);
|
||||
unimplemented.add(Cipher.TLS_DH_RSA_WITH_AES_256_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_DH_RSA_WITH_AES_256_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_DH_RSA_WITH_AES_256_GCM_SHA384);
|
||||
unimplemented.add(Cipher.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_DH_RSA_WITH_SEED_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_ECDH_ECDSA_WITH_NULL_SHA);
|
||||
unimplemented.add(Cipher.TLS_ECDH_ECDSA_WITH_RC4_128_SHA);
|
||||
unimplemented.add(Cipher.TLS_ECDH_ECDSA_WITH_RC4_128_SHA);
|
||||
unimplemented.add(Cipher.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_ECDH_RSA_WITH_NULL_SHA);
|
||||
unimplemented.add(Cipher.TLS_ECDH_RSA_WITH_RC4_128_SHA);
|
||||
unimplemented.add(Cipher.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384);
|
||||
unimplemented.add(Cipher.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384);
|
||||
unimplemented.add(Cipher.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256);
|
||||
unimplemented.add(Cipher.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384);
|
||||
unimplemented.add(Cipher.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256);
|
||||
unimplemented.add(Cipher.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384);
|
||||
unimplemented.add(Cipher.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384);
|
||||
unimplemented.add(Cipher.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256);
|
||||
unimplemented.add(Cipher.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384);
|
||||
unimplemented.add(Cipher.TLS_RSA_WITH_RC4_128_MD5);
|
||||
unimplemented.add(Cipher.TLS_DH_anon_WITH_RC4_128_MD5);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_PSK_WITH_RC4_128_SHA);
|
||||
unimplemented.add(Cipher.TLS_RSA_PSK_WITH_RC4_128_SHA);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_RSA_WITH_RC4_128_SHA);
|
||||
unimplemented.add(Cipher.TLS_RSA_WITH_RC4_128_SHA);
|
||||
unimplemented.add(Cipher.TLS_PSK_WITH_RC4_128_SHA);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA);
|
||||
unimplemented.add(Cipher.TLS_DHE_PSK_WITH_RC4_128_SHA);
|
||||
unimplemented.add(Cipher.TLS_ECDH_anon_WITH_RC4_128_SHA);
|
||||
// 3DES requires a compile time switch to enable. Treat as removed.
|
||||
unimplemented.add(Cipher.TLS_PSK_WITH_3DES_EDE_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_DH_anon_WITH_3DES_EDE_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_RSA_WITH_3DES_EDE_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA);
|
||||
unimplemented.add(Cipher.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA);
|
||||
}
|
||||
|
||||
if (VERSION < 10101) {
|
||||
// These were implemented in 1.1.1 so won't be available in any
|
||||
// earlier version
|
||||
unimplemented.add(Cipher.TLS_RSA_WITH_ARIA_128_GCM_SHA256);
|
||||
unimplemented.add(Cipher.TLS_RSA_WITH_ARIA_256_GCM_SHA384);
|
||||
unimplemented.add(Cipher.TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256);
|
||||
unimplemented.add(Cipher.TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384);
|
||||
unimplemented.add(Cipher.TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256);
|
||||
unimplemented.add(Cipher.TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256);
|
||||
unimplemented.add(Cipher.TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384);
|
||||
unimplemented.add(Cipher.TLS_PSK_WITH_ARIA_128_GCM_SHA256);
|
||||
unimplemented.add(Cipher.TLS_PSK_WITH_ARIA_256_GCM_SHA384);
|
||||
unimplemented.add(Cipher.TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256);
|
||||
unimplemented.add(Cipher.TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384);
|
||||
unimplemented.add(Cipher.TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256);
|
||||
unimplemented.add(Cipher.TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384);
|
||||
}
|
||||
|
||||
String skipCiphers = System.getProperty("tomcat.test.openssl.unimplemented", "");
|
||||
if (!skipCiphers.isEmpty()) {
|
||||
String[] skip = skipCiphers.split(",");
|
||||
for (Cipher c : Cipher.values()) {
|
||||
for (String s : skip) {
|
||||
if (c.toString().contains(s)) {
|
||||
unimplemented.add(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OPENSSL_UNIMPLEMENTED_CIPHERS = Collections.unmodifiableSet(unimplemented);
|
||||
|
||||
Map<String,String> renamed = new HashMap<>();
|
||||
renamed.put("ECDH-ECDSA-RC4-SHA+SSLv3", "ECDH-ECDSA-RC4-SHA+TLSv1");
|
||||
renamed.put("ECDHE-ECDSA-NULL-SHA+SSLv3", "ECDHE-ECDSA-NULL-SHA+TLSv1");
|
||||
renamed.put("ECDHE-ECDSA-DES-CBC3-SHA+SSLv3", "ECDHE-ECDSA-DES-CBC3-SHA+TLSv1");
|
||||
renamed.put("ECDHE-ECDSA-AES128-SHA+SSLv3", "ECDHE-ECDSA-AES128-SHA+TLSv1");
|
||||
renamed.put("ECDHE-ECDSA-AES256-SHA+SSLv3", "ECDHE-ECDSA-AES256-SHA+TLSv1");
|
||||
renamed.put("ECDHE-RSA-NULL-SHA+SSLv3", "ECDHE-RSA-NULL-SHA+TLSv1");
|
||||
renamed.put("ECDHE-RSA-RC4-SHA+SSLv3", "ECDHE-RSA-RC4-SHA+TLSv1");
|
||||
renamed.put("ECDHE-RSA-DES-CBC3-SHA+SSLv3", "ECDHE-RSA-DES-CBC3-SHA+TLSv1");
|
||||
renamed.put("ECDHE-RSA-AES128-SHA+SSLv3", "ECDHE-RSA-AES128-SHA+TLSv1");
|
||||
renamed.put("ECDHE-RSA-AES256-SHA+SSLv3", "ECDHE-RSA-AES256-SHA+TLSv1");
|
||||
renamed.put("AECDH-NULL-SHA+SSLv3", "AECDH-NULL-SHA+TLSv1");
|
||||
renamed.put("AECDH-RC4-SHA+SSLv3", "AECDH-RC4-SHA+TLSv1");
|
||||
renamed.put("AECDH-DES-CBC3-SHA+SSLv3", "AECDH-DES-CBC3-SHA+TLSv1");
|
||||
renamed.put("AECDH-AES128-SHA+SSLv3", "AECDH-AES128-SHA+TLSv1");
|
||||
renamed.put("AECDH-AES256-SHA+SSLv3", "AECDH-AES256-SHA+TLSv1");
|
||||
renamed.put("ECDHE-PSK-RC4-SHA+SSLv3", "ECDHE-PSK-RC4-SHA+TLSv1");
|
||||
renamed.put("ECDHE-PSK-3DES-EDE-CBC-SHA+SSLv3", "ECDHE-PSK-3DES-EDE-CBC-SHA+TLSv1");
|
||||
renamed.put("ECDHE-PSK-AES128-CBC-SHA+SSLv3", "ECDHE-PSK-AES128-CBC-SHA+TLSv1");
|
||||
renamed.put("ECDHE-PSK-AES256-CBC-SHA+SSLv3", "ECDHE-PSK-AES256-CBC-SHA+TLSv1");
|
||||
renamed.put("ECDHE-PSK-NULL-SHA+SSLv3", "ECDHE-PSK-NULL-SHA+TLSv1");
|
||||
OPENSSL_RENAMED_CIPHERS = Collections.unmodifiableMap(renamed);
|
||||
}
|
||||
|
||||
|
||||
private TesterOpenSSL() {
|
||||
// Utility class. Hide default constructor.
|
||||
}
|
||||
|
||||
|
||||
public static Set<String> getOpenSSLCiphersAsSet(String specification) throws Exception {
|
||||
String[] ciphers = getOpenSSLCiphersAsExpression(specification).trim().split(":");
|
||||
Set<String> result = new HashSet<>(ciphers.length);
|
||||
for (String cipher : ciphers) {
|
||||
result.add(cipher);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public static String getOpenSSLCiphersAsExpression(String specification) throws Exception {
|
||||
|
||||
List<String> args = new ArrayList<>();
|
||||
// Standard command to list the ciphers
|
||||
args.add("ciphers");
|
||||
args.add("-v");
|
||||
if (VERSION < 10100) {
|
||||
// Need to exclude the GOST ciphers
|
||||
if (specification == null) {
|
||||
specification = "DEFAULT:!aGOST";
|
||||
} else {
|
||||
specification = "!aGOST:" + specification;
|
||||
}
|
||||
}
|
||||
if (VERSION >= 10101) {
|
||||
// Need to exclude the TLSv1.3 ciphers
|
||||
args.add("-ciphersuites");
|
||||
args.add("");
|
||||
}
|
||||
// Include the specification if provided
|
||||
if (specification != null) {
|
||||
args.add(specification);
|
||||
}
|
||||
|
||||
String stdout = executeOpenSSLCommand(args.toArray(new String[args.size()]));
|
||||
|
||||
if (stdout.length() == 0) {
|
||||
return stdout;
|
||||
}
|
||||
|
||||
StringBuilder output = new StringBuilder();
|
||||
boolean first = true;
|
||||
|
||||
// OpenSSL should have returned one cipher per line
|
||||
String ciphers[] = stdout.split("\n");
|
||||
for (String cipher : ciphers) {
|
||||
// Handle rename for 1.1.0 onwards
|
||||
cipher = cipher.replaceAll("EDH", "DHE");
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
output.append(':');
|
||||
}
|
||||
StringBuilder name = new StringBuilder();
|
||||
|
||||
// Name is first part
|
||||
int i = cipher.indexOf(' ');
|
||||
name.append(cipher.substring(0, i));
|
||||
|
||||
// Advance i past the space
|
||||
while (Character.isWhitespace(cipher.charAt(i))) {
|
||||
i++;
|
||||
}
|
||||
|
||||
// Protocol is the second
|
||||
int j = cipher.indexOf(' ', i);
|
||||
name.append('+');
|
||||
name.append(cipher.substring(i, j));
|
||||
|
||||
// More renames
|
||||
if (OPENSSL_RENAMED_CIPHERS.containsKey(name.toString())) {
|
||||
output.append(OPENSSL_RENAMED_CIPHERS.get(name.toString()));
|
||||
} else {
|
||||
output.append(name.toString());
|
||||
}
|
||||
}
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Use this method to filter parser results when comparing them to OpenSSL
|
||||
* results to take account of unimplemented cipher suites.
|
||||
*/
|
||||
public static void removeUnimplementedCiphersJsse(List<String> list) {
|
||||
for (Cipher cipher : OPENSSL_UNIMPLEMENTED_CIPHERS) {
|
||||
for (String jsseName : cipher.getJsseNames()) {
|
||||
list.remove(jsseName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static String executeOpenSSLCommand(String... args) throws IOException {
|
||||
String openSSLPath = System.getProperty("tomcat.test.openssl.path");
|
||||
String openSSLLibPath = null;
|
||||
if (openSSLPath == null || openSSLPath.length() == 0) {
|
||||
openSSLPath = "openssl";
|
||||
} else {
|
||||
// Explicit OpenSSL path may also need explicit lib path
|
||||
// (e.g. Gump needs this)
|
||||
openSSLLibPath = openSSLPath.substring(0, openSSLPath.lastIndexOf('/'));
|
||||
openSSLLibPath = openSSLLibPath + "/../lib";
|
||||
}
|
||||
List<String> cmd = new ArrayList<>();
|
||||
cmd.add(openSSLPath);
|
||||
for (String arg : args) {
|
||||
cmd.add(arg);
|
||||
}
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder(cmd.toArray(new String[cmd.size()]));
|
||||
|
||||
if (openSSLLibPath != null) {
|
||||
Map<String,String> env = pb.environment();
|
||||
String libraryPath = env.get("LD_LIBRARY_PATH");
|
||||
if (libraryPath == null) {
|
||||
libraryPath = openSSLLibPath;
|
||||
} else {
|
||||
libraryPath = libraryPath + ":" + openSSLLibPath;
|
||||
}
|
||||
env.put("LD_LIBRARY_PATH", libraryPath);
|
||||
}
|
||||
|
||||
Process p = pb.start();
|
||||
|
||||
InputStreamToText stdout = new InputStreamToText(p.getInputStream());
|
||||
InputStreamToText stderr = new InputStreamToText(p.getErrorStream());
|
||||
|
||||
Thread t1 = new Thread(stdout);
|
||||
t1.setName("OpenSSL stdout reader");
|
||||
t1.start();
|
||||
|
||||
Thread t2 = new Thread(stderr);
|
||||
t2.setName("OpenSSL stderr reader");
|
||||
t2.start();
|
||||
|
||||
try {
|
||||
t1.join();
|
||||
t2.join();
|
||||
} catch (InterruptedException e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
|
||||
String errorText = stderr.getText();
|
||||
if (errorText.length() > 0) {
|
||||
System.err.println(errorText);
|
||||
}
|
||||
|
||||
return stdout.getText().trim();
|
||||
}
|
||||
|
||||
private static class InputStreamToText implements Runnable {
|
||||
|
||||
private final ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
private final InputStream is;
|
||||
|
||||
InputStreamToText(InputStream is) {
|
||||
this.is = is;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
IOTools.flow(is, baos);
|
||||
} catch (IOException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return baos.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user