diff options
4 files changed, 131 insertions, 8 deletions
diff --git a/luni/src/main/java/javax/net/ssl/SSLEngine.java b/luni/src/main/java/javax/net/ssl/SSLEngine.java index f2b051c..3ba3450 100644 --- a/luni/src/main/java/javax/net/ssl/SSLEngine.java +++ b/luni/src/main/java/javax/net/ssl/SSLEngine.java @@ -544,12 +544,12 @@ import java.nio.ByteBuffer; * <tr> * <td>TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA</td> * <td>21+</td> - * <td></td> + * <td>21+</td> * </tr> * <tr> * <td>TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA</td> * <td>21+</td> - * <td></td> + * <td>21+</td> * </tr> * <tr> * <td>TLS_NULL_WITH_NULL_NULL</td> @@ -564,12 +564,12 @@ import java.nio.ByteBuffer; * <tr> * <td>TLS_PSK_WITH_AES_128_CBC_SHA</td> * <td>21+</td> - * <td></td> + * <td>21+</td> * </tr> * <tr> * <td>TLS_PSK_WITH_AES_256_CBC_SHA</td> * <td>21+</td> - * <td></td> + * <td>21+</td> * </tr> * <tr> * <td>TLS_PSK_WITH_RC4_128_SHA</td> @@ -639,6 +639,9 @@ import java.nio.ByteBuffer; * </tbody> * </table> * + * <p><em>NOTE</em>: PSK cipher suites are enabled by default only if the {@code SSLContext} through + * which the engine was created has been initialized with a {@code PSKKeyManager}. + * * @since 1.5 */ public abstract class SSLEngine { diff --git a/luni/src/main/java/javax/net/ssl/SSLSocket.java b/luni/src/main/java/javax/net/ssl/SSLSocket.java index af97fa8..33a88b6 100644 --- a/luni/src/main/java/javax/net/ssl/SSLSocket.java +++ b/luni/src/main/java/javax/net/ssl/SSLSocket.java @@ -348,12 +348,12 @@ import java.net.UnknownHostException; * <tr> * <td>TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA</td> * <td>21+</td> - * <td></td> + * <td>21+</td> * </tr> * <tr> * <td>TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA</td> * <td>21+</td> - * <td></td> + * <td>21+</td> * </tr> * <tr> * <td>TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA</td> @@ -528,12 +528,12 @@ import java.net.UnknownHostException; * <tr> * <td>TLS_PSK_WITH_AES_128_CBC_SHA</td> * <td>21+</td> - * <td></td> + * <td>21+</td> * </tr> * <tr> * <td>TLS_PSK_WITH_AES_256_CBC_SHA</td> * <td>21+</td> - * <td></td> + * <td>21+</td> * </tr> * <tr> * <td>TLS_PSK_WITH_RC4_128_SHA</td> @@ -578,6 +578,9 @@ import java.net.UnknownHostException; * </tbody> * </table> * + * <p><em>NOTE</em>: PSK cipher suites are enabled by default only if the {@code SSLContext} through + * which the socket was created has been initialized with a {@code PSKKeyManager}. + * * <p>API Levels 1 to 8 use OpenSSL names for cipher suites. The table below * lists these OpenSSL names and their corresponding standard names used in API * Levels 9 and newer. diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLContextTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLContextTest.java index 0e13fb0..dccadbd 100644 --- a/luni/src/test/java/libcore/javax/net/ssl/SSLContextTest.java +++ b/luni/src/test/java/libcore/javax/net/ssl/SSLContextTest.java @@ -24,7 +24,12 @@ import java.security.NoSuchAlgorithmException; import java.security.Provider; import java.security.Security; import java.security.UnrecoverableKeyException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import java.util.concurrent.Callable; +import libcore.io.IoUtils; import libcore.java.security.StandardNames; import javax.net.ServerSocketFactory; import javax.net.SocketFactory; @@ -34,12 +39,15 @@ import javax.net.ssl.KeyManagerFactorySpi; import javax.net.ssl.ManagerFactoryParameters; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLServerSocketFactory; import javax.net.ssl.SSLSessionContext; +import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.TrustManagerFactorySpi; +import javax.net.ssl.X509KeyManager; import junit.framework.AssertionFailedError; import junit.framework.TestCase; @@ -85,6 +93,94 @@ public class SSLContextTest extends TestCase { } } + public void test_SSLContext_pskOnlyConfiguration_defaultProviderOnly() throws Exception { + // Test the scenario where only a PSKKeyManager is provided and no TrustManagers are + // provided. + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init( + new KeyManager[] { + PSKKeyManagerProxy.getConscryptPSKKeyManager(new PSKKeyManagerProxy()) + }, + new TrustManager[0], + null); + List<String> expectedCipherSuites = + new ArrayList<String>(StandardNames.CIPHER_SUITES_DEFAULT_PSK); + expectedCipherSuites.add(StandardNames.CIPHER_SUITE_SECURE_RENEGOTIATION); + assertEnabledCipherSuites(expectedCipherSuites, sslContext); + } + + public void test_SSLContext_x509AndPskConfiguration_defaultProviderOnly() throws Exception { + // Test the scenario where an X509TrustManager and PSKKeyManager are provided. + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init( + new KeyManager[] { + PSKKeyManagerProxy.getConscryptPSKKeyManager(new PSKKeyManagerProxy()) + }, + null, // Use default trust managers, one of which is an X.509 one. + null); + List<String> expectedCipherSuites = + new ArrayList<String>(StandardNames.CIPHER_SUITES_DEFAULT_PSK); + expectedCipherSuites.addAll(StandardNames.CIPHER_SUITES_DEFAULT); + assertEnabledCipherSuites(expectedCipherSuites, sslContext); + + // Test the scenario where an X509KeyManager and PSKKeyManager are provided. + sslContext = SSLContext.getInstance("TLS"); + // Just an arbitrary X509KeyManager -- it won't be invoked in this test. + X509KeyManager x509KeyManager = new RandomPrivateKeyX509ExtendedKeyManager(null); + sslContext.init( + new KeyManager[] { + x509KeyManager, + PSKKeyManagerProxy.getConscryptPSKKeyManager(new PSKKeyManagerProxy()) + }, + new TrustManager[0], + null); + assertEnabledCipherSuites(expectedCipherSuites, sslContext); + } + + public void test_SSLContext_emptyConfiguration_defaultProviderOnly() throws Exception { + // Test the scenario where neither X.509 nor PSK KeyManagers or TrustManagers are provided. + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init( + new KeyManager[0], + new TrustManager[0], + null); + assertEnabledCipherSuites( + Arrays.asList(StandardNames.CIPHER_SUITE_SECURE_RENEGOTIATION), + sslContext); + } + + private static void assertEnabledCipherSuites( + List<String> expectedCipherSuites, SSLContext sslContext) throws Exception { + assertContentsInOrder( + expectedCipherSuites, sslContext.createSSLEngine().getEnabledCipherSuites()); + assertContentsInOrder( + expectedCipherSuites, + sslContext.createSSLEngine().getSSLParameters().getCipherSuites()); + assertContentsInOrder( + expectedCipherSuites, sslContext.getSocketFactory().getDefaultCipherSuites()); + assertContentsInOrder( + expectedCipherSuites, sslContext.getServerSocketFactory().getDefaultCipherSuites()); + + SSLSocket sslSocket = (SSLSocket) sslContext.getSocketFactory().createSocket(); + try { + assertContentsInOrder( + expectedCipherSuites, sslSocket.getEnabledCipherSuites()); + assertContentsInOrder( + expectedCipherSuites, sslSocket.getSSLParameters().getCipherSuites()); + } finally { + IoUtils.closeQuietly(sslSocket); + } + + SSLServerSocket sslServerSocket = + (SSLServerSocket) sslContext.getServerSocketFactory().createServerSocket(); + try { + assertContentsInOrder( + expectedCipherSuites, sslServerSocket.getEnabledCipherSuites()); + } finally { + IoUtils.closeQuietly(sslSocket); + } + } + public void test_SSLContext_getInstance() throws Exception { try { SSLContext.getInstance(null); @@ -463,4 +559,16 @@ public class SSLContextTest extends TestCase { assertTrue(testContext.port != 0); testContext.close(); } + + private static void assertContentsInOrder(List<String> expected, String... actual) { + if (expected.size() != actual.length) { + fail("Unexpected length. Expected len <" + expected.size() + + ">, actual len <" + actual.length + ">, expected <" + expected + + ">, actual <" + Arrays.asList(actual) + ">"); + } + if (!expected.equals(Arrays.asList(actual))) { + fail("Unexpected element(s). Expected <" + expected + + ">, actual <" + Arrays.asList(actual) + ">" ); + } + } } diff --git a/support/src/test/java/libcore/java/security/StandardNames.java b/support/src/test/java/libcore/java/security/StandardNames.java index 719c3b7..a526c2e 100644 --- a/support/src/test/java/libcore/java/security/StandardNames.java +++ b/support/src/test/java/libcore/java/security/StandardNames.java @@ -863,6 +863,15 @@ public final class StandardNames extends Assert { "SSL_RSA_WITH_RC4_128_SHA", CIPHER_SUITE_SECURE_RENEGOTIATION); + // NOTE: This list needs to be kept in sync with Javadoc of javax.net.ssl.SSLSocket and + // javax.net.ssl.SSLEngine. + public static final List<String> CIPHER_SUITES_DEFAULT_PSK = Arrays.asList( + "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA", + "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA", + "TLS_PSK_WITH_AES_128_CBC_SHA", + "TLS_PSK_WITH_AES_256_CBC_SHA" + ); + private static final Set<String> PERMITTED_DEFAULT_KEY_EXCHANGE_ALGS = new HashSet<String>(Arrays.asList("RSA", "DHE_RSA", |