From e6d19bf654911a72e59a2980a6542a7e6e5fcf4f Mon Sep 17 00:00:00 2001 From: "Neil A. Wilson" Date: Fri, 6 Dec 2019 16:17:51 -0600 Subject: [PATCH] Allow selecting supported cipher suites Updated the TLS cipher suite selector to provide a static method to pare down a provided collection of TLS cipher suite names to include only those suites that are supported by the JVM. --- .../util/ssl/TLSCipherSuiteSelector.java | 49 ++++++++++++++++ .../ssl/TLSCipherSuiteSelectorTestCase.java | 56 +++++++++++++++++++ 2 files changed, 105 insertions(+) diff --git a/src/com/unboundid/util/ssl/TLSCipherSuiteSelector.java b/src/com/unboundid/util/ssl/TLSCipherSuiteSelector.java index ef015038c..7168d87bc 100644 --- a/src/com/unboundid/util/ssl/TLSCipherSuiteSelector.java +++ b/src/com/unboundid/util/ssl/TLSCipherSuiteSelector.java @@ -26,9 +26,13 @@ import java.io.PrintStream; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; import java.util.TreeMap; @@ -637,4 +641,49 @@ private void generateOutput(final PrintStream s) s.println("* " + cipherSuite); } } + + + + /** + * Filters the provided collection of potential cipher suite names to retrieve + * a set of the suites that are supported by the JVM. + * + * @param potentialSuiteNames The collection of cipher suite names to be + * filtered. + * + * @return The set of provided cipher suites that are supported by the JVM, + * or an empty set if none of the potential provided suite names are + * supported by the JVM. + */ + public static Set selectSupportedCipherSuites( + final Collection potentialSuiteNames) + { + if (potentialSuiteNames == null) + { + return Collections.emptySet(); + } + + final int capacity = + StaticUtils.computeMapCapacity(INSTANCE.supportedCipherSuites.size()); + final Map supportedMap = new HashMap<>(capacity); + for (final String supportedSuite : INSTANCE.supportedCipherSuites) + { + supportedMap.put( + StaticUtils.toUpperCase(supportedSuite).replace('-', '_'), + supportedSuite); + } + + final Set selectedSet = new LinkedHashSet<>(capacity); + for (final String potentialSuite : potentialSuiteNames) + { + final String supportedName = supportedMap.get( + StaticUtils.toUpperCase(potentialSuite).replace('-', '_')); + if (supportedName != null) + { + selectedSet.add(supportedName); + } + } + + return Collections.unmodifiableSet(selectedSet); + } } diff --git a/tests/unit/src/com/unboundid/util/ssl/TLSCipherSuiteSelectorTestCase.java b/tests/unit/src/com/unboundid/util/ssl/TLSCipherSuiteSelectorTestCase.java index d462b63bc..1a9beaf37 100644 --- a/tests/unit/src/com/unboundid/util/ssl/TLSCipherSuiteSelectorTestCase.java +++ b/tests/unit/src/com/unboundid/util/ssl/TLSCipherSuiteSelectorTestCase.java @@ -29,6 +29,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; @@ -174,6 +175,13 @@ else if (line.isEmpty() || line.startsWith("#")) // Make sure that the non-recommended suites isn't empty. assertNotNull(selectedPair.getSecond()); assertFalse(selectedPair.getSecond().isEmpty()); + + + // Get the supported set of suites from the complete and pared-down sets. + assertNotNull(TLSCipherSuiteSelector.selectSupportedCipherSuites( + nonParedDownCipherSuiteList)); + assertNotNull(TLSCipherSuiteSelector.selectSupportedCipherSuites( + paredDownCipherSuiteList)); } @@ -225,6 +233,54 @@ public Object[][] getCipherSuiteFileNames() + /** + * Provides test coverage for the {@code selectSupportedCipherSuites} method. + * + * @throws Exception If an unexpected problem occurs. + */ + @Test() + public void testSelectSupportedCipherSuites() + throws Exception + { + Set selectedSuites = + TLSCipherSuiteSelector.selectSupportedCipherSuites(null); + assertNotNull(selectedSuites); + assertTrue(selectedSuites.isEmpty()); + + selectedSuites = TLSCipherSuiteSelector.selectSupportedCipherSuites( + Collections.emptyList()); + assertNotNull(selectedSuites); + assertTrue(selectedSuites.isEmpty()); + + selectedSuites = TLSCipherSuiteSelector.selectSupportedCipherSuites( + Collections.emptySet()); + assertNotNull(selectedSuites); + assertTrue(selectedSuites.isEmpty()); + + selectedSuites = TLSCipherSuiteSelector.selectSupportedCipherSuites( + TLSCipherSuiteSelector.getSupportedCipherSuites()); + assertNotNull(selectedSuites); + assertFalse(selectedSuites.isEmpty()); + assertEquals(selectedSuites, + TLSCipherSuiteSelector.getSupportedCipherSuites()): + + selectedSuites = TLSCipherSuiteSelector.selectSupportedCipherSuites( + TLSCipherSuiteSelector.getDefaultCipherSuites()); + assertNotNull(selectedSuites); + assertFalse(selectedSuites.isEmpty()); + assertEquals(selectedSuites, + TLSCipherSuiteSelector.getDefaultCipherSuites()): + + selectedSuites = TLSCipherSuiteSelector.selectSupportedCipherSuites( + TLSCipherSuiteSelector.getRecommendedCipherSuites()); + assertNotNull(selectedSuites); + assertFalse(selectedSuites.isEmpty()); + assertEquals(selectedSuites, + TLSCipherSuiteSelector.getRecommendedCipherSuites()): + } + + + /** * Tests the ability to invoke the TLS cipher suite selector as a command-line * tool.