diff options
author | Kenny Root <kroot@google.com> | 2014-04-21 22:17:32 +0000 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2014-04-21 22:17:32 +0000 |
commit | 4ebbeff7b898868105c369242e1646ac8aeb53f7 (patch) | |
tree | c9920764a4ef7cf46eb0386d3b012302f556d5df | |
parent | 0190a26a35bb20911b6cce5afdfa03597537e592 (diff) | |
parent | c501440e3fc82cbb427a441e81cfb534c137d9e6 (diff) | |
download | libcore-4ebbeff7b898868105c369242e1646ac8aeb53f7.zip libcore-4ebbeff7b898868105c369242e1646ac8aeb53f7.tar.gz libcore-4ebbeff7b898868105c369242e1646ac8aeb53f7.tar.bz2 |
am c501440e: am 915faabe: Merge changes I7db8e513,I564283bb
* commit 'c501440e3fc82cbb427a441e81cfb534c137d9e6':
Update SSLEngineTest for OpenSSL
Update SSLEngineTest for RI
7 files changed, 213 insertions, 193 deletions
diff --git a/expectations/knownfailures.txt b/expectations/knownfailures.txt index 66b39fb..276e781 100644 --- a/expectations/knownfailures.txt +++ b/expectations/knownfailures.txt @@ -939,49 +939,6 @@ name: "libcore.java.sql.OldStatementTest#testGetUpdateCount" }, { - description: "Handshake Status is never finished. NPE in ClientSessionContext$HostAndPort.hashCode() when host - is null", - bug: 3403706, - name: "tests.api.javax.net.ssl.SSLEngineTest#testHandshake" -}, -{ - description: "com.android.org.conscrypt.SSLEngineImpl#getDelegatedTask() throws NPE instead of - returning null", - bug: 3403706, - name: "tests.api.javax.net.ssl.SSLEngineTest#test_getDelegatedTask" -}, -{ - description: "Fixed in DonutBurger, boundary checks missing", - bug: 3403706, - name: "tests.api.javax.net.ssl.SSLEngineTest#test_unwrap_02" -}, -{ - description: "Fixed on DonutBurger, Wrong Exception thrown", - bug: 3403706, - names: [ - "tests.api.javax.net.ssl.SSLEngineTest#test_unwrap_03", - "tests.api.javax.net.ssl.SSLEngineTest#test_unwrap_04", - "tests.api.javax.net.ssl.SSLEngineTest#test_unwrap_ByteBuffer$ByteBuffer_02", - "tests.api.javax.net.ssl.SSLEngineTest#test_unwrap_ByteBuffer$ByteBuffer_03", - "tests.api.javax.net.ssl.SSLEngineTest#test_unwrap_ByteBuffer_ByteBuffer_02", - "tests.api.javax.net.ssl.SSLEngineTest#test_unwrap_ByteBuffer_ByteBuffer_03" - ] -}, -{ - description: "Fixed in DonutBurger, boundary checks missing", - bug: 3403706, - name: "tests.api.javax.net.ssl.SSLEngineTest#test_wrap_02" -}, -{ - description: "Fixed on DonutBurger, Wrong Exception thrown", - bug: 3403706, - names: [ - "tests.api.javax.net.ssl.SSLEngineTest#test_wrap_04", - "tests.api.javax.net.ssl.SSLEngineTest#test_wrap_ByteBuffer$ByteBuffer_03", - "tests.api.javax.net.ssl.SSLEngineTest#test_wrap_ByteBuffer_ByteBuffer_03" - ] -}, -{ description: "ManagerFactoryParameters object is not supported and InvalidAlgorithmParameterException was thrown.", bug: 3403706, @@ -993,26 +950,6 @@ name: "tests.api.javax.net.ssl.HostnameVerifierTest#testVerifyIpAddress" }, { - description: "NO SERVER CERTIFICATE FOUND - selectSuite should not pick a suite that needs a certificate if it is missing", - bug: 3045163, - name: "libcore.javax.net.ssl.SSLEngineTest#test_SSLEngine_beginHandshake_noKeyStore" -}, -{ - description: "AlertException instead of SSLException", - bug: 3045163, - name: "libcore.javax.net.ssl.SSLEngineTest#test_SSLEngine_setEnableSessionCreation_client" -}, -{ - description: "SSLException instead of failure to handshake", - bug: 3045163, - name: "libcore.javax.net.ssl.SSLEngineTest#test_SSLEngine_setEnableSessionCreation_server" -}, -{ - description: "SSLHandshakeException instead of failure to handshake", - bug: 3045163, - name: "libcore.javax.net.ssl.SSLEngineTest#test_SSLEngine_setUseClientMode" -}, -{ description: "method test fails once in a while. Cannot be sure that exception is thrown in every test execution.", bug: 3403706, name: "libcore.sqlite.OldDatabaseTest#testBusy_handler" diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java index 1bd1347..a7d0df2 100644 --- a/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java +++ b/luni/src/test/java/libcore/javax/net/ssl/SSLEngineTest.java @@ -82,9 +82,7 @@ public class SSLEngineTest extends TestCase { .ca(true) .build(); test_SSLEngine_getSupportedCipherSuites_connect(testKeyStore, false); - if (StandardNames.IS_RI) { - test_SSLEngine_getSupportedCipherSuites_connect(testKeyStore, true); - } + test_SSLEngine_getSupportedCipherSuites_connect(testKeyStore, true); } private void test_SSLEngine_getSupportedCipherSuites_connect(TestKeyStore testKeyStore, boolean secureRenegotiation) @@ -133,86 +131,96 @@ public class SSLEngineTest extends TestCase { testKeyStore.keyManagers[replaceIndex] = originalKeyManager; } + // To catch all the errors. + StringBuilder error = new StringBuilder(); + String[] cipherSuites = c.clientContext.createSSLEngine().getSupportedCipherSuites(); for (String cipherSuite : cipherSuites) { - boolean errorExpected = StandardNames.IS_RI && cipherSuite.endsWith("_SHA256"); try { - /* - * TLS_EMPTY_RENEGOTIATION_INFO_SCSV cannot be used on - * its own, but instead in conjunction with other - * cipher suites. - */ - if (cipherSuite.equals(StandardNames.CIPHER_SUITE_SECURE_RENEGOTIATION)) { - continue; - } - /* - * Kerberos cipher suites require external setup. See "Kerberos Requirements" in - * https://java.sun.com/j2se/1.5.0/docs/guide/security/jsse/JSSERefGuide.html - * #KRBRequire - */ - if (cipherSuite.startsWith("TLS_KRB5_")) { - continue; - } + // Skip cipher suites that are obsoleted. + if (StandardNames.IS_RI && "TLSv1.2".equals(c.clientContext.getProtocol()) + && StandardNames.CIPHER_SUITES_OBSOLETE_TLS12.contains(cipherSuite)) { + continue; + } + /* + * TLS_EMPTY_RENEGOTIATION_INFO_SCSV cannot be used on + * its own, but instead in conjunction with other + * cipher suites. + */ + if (cipherSuite.equals(StandardNames.CIPHER_SUITE_SECURE_RENEGOTIATION)) { + continue; + } + /* + * Kerberos cipher suites require external setup. See "Kerberos Requirements" in + * https://java.sun.com/j2se/1.5.0/docs/guide/security/jsse/JSSERefGuide.html + * #KRBRequire + */ + if (cipherSuite.startsWith("TLS_KRB5_")) { + continue; + } - final String[] cipherSuiteArray - = (secureRenegotiation - ? new String[] { cipherSuite, - StandardNames.CIPHER_SUITE_SECURE_RENEGOTIATION } - : new String[] { cipherSuite }); + final String[] cipherSuiteArray + = (secureRenegotiation + ? new String[] { cipherSuite, + StandardNames.CIPHER_SUITE_SECURE_RENEGOTIATION } + : new String[] { cipherSuite }); - // Check that handshake succeeds. - TestSSLEnginePair pair = TestSSLEnginePair.create(c, new TestSSLEnginePair.Hooks() { - @Override - void beforeBeginHandshake(SSLEngine client, SSLEngine server) { - client.setEnabledCipherSuites(cipherSuiteArray); - server.setEnabledCipherSuites(cipherSuiteArray); - } - }); - assertConnected(pair); - - boolean needsRecordSplit = - ("TLS".equalsIgnoreCase(c.clientContext.getProtocol()) - || "SSLv3".equalsIgnoreCase(c.clientContext.getProtocol())) - && cipherSuite.contains("_CBC_"); - - assertSendsCorrectly("This is the client. Hello!".getBytes(), - pair.client, pair.server, needsRecordSplit); - assertSendsCorrectly("This is the server. Hi!".getBytes(), - pair.server, pair.client, needsRecordSplit); - assertFalse(errorExpected); - - // Check that handshake fails when the server does not possess the private key - // corresponding to the server's certificate. This is achieved by using SSLContext - // cWithWrongPrivateKeys whose KeyManager returns wrong private keys that match - // the algorithm (and parameters) of the correct keys. - if (!cipherSuite.contains("_anon_")) { - // The identity of the server is verified only in non-anonymous key exchanges. - try { - TestSSLEnginePair p = TestSSLEnginePair.create( - cWithWrongPrivateKeys, new TestSSLEnginePair.Hooks() { - @Override - void beforeBeginHandshake(SSLEngine client, SSLEngine server) { - client.setEnabledCipherSuites(cipherSuiteArray); - server.setEnabledCipherSuites(cipherSuiteArray); - } - }); - assertConnected(p); - fail("Handshake succeeded for " + cipherSuite - + " despite server not having the correct private key"); - } catch (IOException expected) {} - } - } catch (Exception maybeExpected) { - if (!errorExpected) { - throw new Exception("Problem trying to connect cipher suite " + cipherSuite, - maybeExpected); + // Check that handshake succeeds. + TestSSLEnginePair pair = TestSSLEnginePair.create(c, new TestSSLEnginePair.Hooks() { + @Override + void beforeBeginHandshake(SSLEngine client, SSLEngine server) { + client.setEnabledCipherSuites(cipherSuiteArray); + server.setEnabledCipherSuites(cipherSuiteArray); } + }); + assertConnected(pair); + + boolean needsRecordSplit = + ("TLS".equalsIgnoreCase(c.clientContext.getProtocol()) + || "SSLv3".equalsIgnoreCase(c.clientContext.getProtocol())) + && cipherSuite.contains("_CBC_"); + + assertSendsCorrectly("This is the client. Hello!".getBytes(), + pair.client, pair.server, needsRecordSplit); + assertSendsCorrectly("This is the server. Hi!".getBytes(), + pair.server, pair.client, needsRecordSplit); + + // Check that handshake fails when the server does not possess the private key + // corresponding to the server's certificate. This is achieved by using SSLContext + // cWithWrongPrivateKeys whose KeyManager returns wrong private keys that match + // the algorithm (and parameters) of the correct keys. + if (!cipherSuite.contains("_anon_")) { + // The identity of the server is verified only in non-anonymous key exchanges. + try { + TestSSLEnginePair p = TestSSLEnginePair.create( + cWithWrongPrivateKeys, new TestSSLEnginePair.Hooks() { + @Override + void beforeBeginHandshake(SSLEngine client, SSLEngine server) { + client.setEnabledCipherSuites(cipherSuiteArray); + server.setEnabledCipherSuites(cipherSuiteArray); + } + }); + assertNotConnected(p); + } catch (IOException expected) {} + } + } catch (Exception e) { + String message = ("Problem trying to connect cipher suite " + cipherSuite); + System.out.println(message); + e.printStackTrace(); + error.append(message); + error.append('\n'); } } c.close(); + + if (error.length() > 0) { + throw new Exception("One or more problems in " + + "test_SSLEngine_getSupportedCipherSuites_connect:\n" + error); + } } - private void assertSendsCorrectly(final byte[] sourceBytes, SSLEngine source, SSLEngine dest, - boolean needsRecordSplit) throws SSLException { + private static void assertSendsCorrectly(final byte[] sourceBytes, SSLEngine source, + SSLEngine dest, boolean needsRecordSplit) throws SSLException { ByteBuffer sourceOut = ByteBuffer.wrap(sourceBytes); SSLSession sourceSession = source.getSession(); ByteBuffer sourceToDest = ByteBuffer.allocate(sourceSession.getPacketBufferSize()); @@ -327,9 +335,19 @@ public class SSLEngineTest extends TestCase { e.setEnabledProtocols(e.getSupportedProtocols()); // Check that setEnabledProtocols affects getEnabledProtocols - String[] protocols = new String[] { e.getSupportedProtocols()[0] }; - e.setEnabledProtocols(protocols); - assertEquals(Arrays.asList(protocols), Arrays.asList(e.getEnabledProtocols())); + for (String protocol : e.getSupportedProtocols()) { + if ("SSLv2Hello".equals(protocol)) { + try { + e.setEnabledProtocols(new String[] { protocol }); + fail("Should fail when SSLv2Hello is set by itself"); + } catch (IllegalArgumentException expected) {} + } else { + String[] protocols = new String[] { protocol }; + e.setEnabledProtocols(protocols); + assertEquals(Arrays.deepToString(protocols), + Arrays.deepToString(e.getEnabledProtocols())); + } + } c.close(); } @@ -385,17 +403,34 @@ public class SSLEngineTest extends TestCase { } public void test_SSLEngine_setUseClientMode() throws Exception { + boolean[] finished; + // client is client, server is server - assertConnected(test_SSLEngine_setUseClientMode(true, false)); + finished = new boolean[2]; + assertConnected(test_SSLEngine_setUseClientMode(true, false, finished)); + assertTrue(finished[0]); + assertTrue(finished[1]); // client is server, server is client - assertConnected(test_SSLEngine_setUseClientMode(false, true)); + finished = new boolean[2]; + assertConnected(test_SSLEngine_setUseClientMode(false, true, finished)); + assertTrue(finished[0]); + assertTrue(finished[1]); // both are client - assertNotConnected(test_SSLEngine_setUseClientMode(true, true)); + /* + * Our implementation throws an SSLHandshakeException, but RI just + * stalls forever + */ + try { + assertNotConnected(test_SSLEngine_setUseClientMode(true, true, null)); + assertTrue(StandardNames.IS_RI); + } catch (SSLHandshakeException maybeExpected) { + assertFalse(StandardNames.IS_RI); + } // both are server - assertNotConnected(test_SSLEngine_setUseClientMode(false, false)); + assertNotConnected(test_SSLEngine_setUseClientMode(false, false, null)); } public void test_SSLEngine_setUseClientMode_afterHandshake() throws Exception { @@ -415,7 +450,8 @@ public class SSLEngineTest extends TestCase { } private TestSSLEnginePair test_SSLEngine_setUseClientMode(final boolean clientClientMode, - final boolean serverClientMode) + final boolean serverClientMode, + final boolean[] finished) throws Exception { TestSSLContext c; if (!clientClientMode && serverClientMode) { @@ -430,7 +466,7 @@ public class SSLEngineTest extends TestCase { client.setUseClientMode(clientClientMode); server.setUseClientMode(serverClientMode); } - }); + }, finished); } public void test_SSLEngine_clientAuth() throws Exception { diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java index 5c46406..2911b48 100644 --- a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java +++ b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java @@ -246,9 +246,19 @@ public class SSLSocketTest extends TestCase { ssl.setEnabledProtocols(ssl.getSupportedProtocols()); // Check that setEnabledProtocols affects getEnabledProtocols - String[] protocols = new String[] { ssl.getSupportedProtocols()[0] }; - ssl.setEnabledProtocols(protocols); - assertEquals(Arrays.asList(protocols), Arrays.asList(ssl.getEnabledProtocols())); + for (String protocol : ssl.getSupportedProtocols()) { + if ("SSLv2Hello".equals(protocol)) { + try { + ssl.setEnabledProtocols(new String[] { protocol }); + fail("Should fail when SSLv2Hello is set by itself"); + } catch (IllegalArgumentException expected) {} + } else { + String[] protocols = new String[] { protocol }; + ssl.setEnabledProtocols(protocols); + assertEquals(Arrays.deepToString(protocols), + Arrays.deepToString(ssl.getEnabledProtocols())); + } + } } public void test_SSLSocket_getSession() throws Exception { diff --git a/support/src/test/java/libcore/java/security/StandardNames.java b/support/src/test/java/libcore/java/security/StandardNames.java index 74263f6..da6fcd6 100644 --- a/support/src/test/java/libcore/java/security/StandardNames.java +++ b/support/src/test/java/libcore/java/security/StandardNames.java @@ -583,12 +583,6 @@ public final class StandardNames extends Assert { * do to disable general use of SSLv2. */ SSL_SOCKET_PROTOCOLS.add("SSLv2Hello"); - - // RI doesn't support these by default. - SSL_SOCKET_PROTOCOLS_CLIENT_DEFAULT.remove("TLSv1.1"); - SSL_SOCKET_PROTOCOLS_CLIENT_DEFAULT.remove("TLSv1.2"); - SSL_SOCKET_PROTOCOLS_SERVER_DEFAULT.remove("TLSv1.1"); - SSL_SOCKET_PROTOCOLS_SERVER_DEFAULT.remove("TLSv1.2"); } } @@ -596,12 +590,8 @@ public final class StandardNames extends Assert { public static final Set<String> SSL_SOCKET_PROTOCOLS_DEFAULT_SSLENGINE = new HashSet<String>(SSL_SOCKET_PROTOCOLS_CLIENT_DEFAULT); static { - // No TLSv1.1 or TLSv1.2 support on SSLEngine based provider - if (!IS_RI) { - SSL_SOCKET_PROTOCOLS_SSLENGINE.remove("TLSv1.1"); - SSL_SOCKET_PROTOCOLS_SSLENGINE.remove("TLSv1.2"); - SSL_SOCKET_PROTOCOLS_DEFAULT_SSLENGINE.remove("TLSv1.1"); - SSL_SOCKET_PROTOCOLS_DEFAULT_SSLENGINE.remove("TLSv1.2"); + if (IS_RI) { + SSL_SOCKET_PROTOCOLS_DEFAULT_SSLENGINE.add("SSLv2Hello"); } } @@ -790,16 +780,47 @@ public final class StandardNames extends Assert { CIPHER_SUITES = (IS_RI) ? CIPHER_SUITES_RI : CIPHER_SUITES_OPENSSL; } + /** + * Cipher suites that are not negotiated when TLSv1.2 is selected on the RI. + */ + public static final List<String> CIPHER_SUITES_OBSOLETE_TLS12 = + Arrays.asList( + "SSL_RSA_WITH_DES_CBC_SHA", + "SSL_DHE_RSA_WITH_DES_CBC_SHA", + "SSL_DHE_DSS_WITH_DES_CBC_SHA", + "SSL_DH_anon_WITH_DES_CBC_SHA", + "SSL_RSA_EXPORT_WITH_RC4_40_MD5", + "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5", + "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", + "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", + "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", + "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA" + ); + // 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 = (IS_RI) - ? Arrays.asList("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", + ? Arrays.asList("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", + "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", + "TLS_RSA_WITH_AES_256_CBC_SHA256", + "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384", + "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384", + "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256", + "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256", + "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "TLS_RSA_WITH_AES_256_CBC_SHA", "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA", "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA", "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", "TLS_DHE_DSS_WITH_AES_256_CBC_SHA", + "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", + "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", + "TLS_RSA_WITH_AES_128_CBC_SHA256", + "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256", + "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256", + "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", + "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA", @@ -866,28 +887,6 @@ public final class StandardNames extends Assert { public static final List<String> CIPHER_SUITES_DEFAULT_SSLENGINE = new ArrayList<String>(CIPHER_SUITES_DEFAULT); public static final Set<String> CIPHER_SUITES_SSLENGINE = new HashSet<String>(CIPHER_SUITES); - static { - // No Elliptic Curve or TLSv1.2 cipher suite support on SSLEngine based provider - if (!IS_RI) { - Iterator<String> i = CIPHER_SUITES_SSLENGINE.iterator(); - while (i.hasNext()) { - String cs = i.next(); - if (cs.startsWith("TLS_EC") || cs.contains("_SHA256") || cs.contains("_SHA384") - || cs.equals(CIPHER_SUITE_SECURE_RENEGOTIATION)) { - i.remove(); - } - } - - i = CIPHER_SUITES_DEFAULT_SSLENGINE.iterator(); - while (i.hasNext()) { - String cs = i.next(); - if (cs.startsWith("TLS_EC") || cs.contains("_SHA256") || cs.contains("_SHA384") - || cs.equals(CIPHER_SUITE_SECURE_RENEGOTIATION)) { - i.remove(); - } - } - } - } public static final Map<String, Class<? extends KeySpec>> PRIVATE_KEY_SPEC_CLASSES; public static final Map<String, Class<? extends KeySpec>> PUBLIC_KEY_SPEC_CLASSES; diff --git a/support/src/test/java/libcore/javax/net/ssl/RandomPrivateKeyX509ExtendedKeyManager.java b/support/src/test/java/libcore/javax/net/ssl/RandomPrivateKeyX509ExtendedKeyManager.java index fd5cc0b..ce40129 100644 --- a/support/src/test/java/libcore/javax/net/ssl/RandomPrivateKeyX509ExtendedKeyManager.java +++ b/support/src/test/java/libcore/javax/net/ssl/RandomPrivateKeyX509ExtendedKeyManager.java @@ -21,6 +21,7 @@ import java.security.GeneralSecurityException; import java.security.KeyFactory; import java.security.KeyPairGenerator; import java.security.PrivateKey; +import java.security.interfaces.ECPrivateKey; import java.security.spec.DSAParameterSpec; import java.security.spec.DSAPrivateKeySpec; import java.security.spec.RSAPrivateKeySpec; @@ -71,6 +72,10 @@ public class RandomPrivateKeyX509ExtendedKeyManager extends ForwardingX509Extend keyPairGenerator.initialize(new DSAParameterSpec( originalKeySpec.getP(), originalKeySpec.getQ(), originalKeySpec.getG())); result = keyPairGenerator.generateKeyPair().getPrivate(); + } else if ("EC".equals(keyAlgorithm)) { + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(keyAlgorithm); + keyPairGenerator.initialize(((ECPrivateKey) originalPrivateKey).getParams()); + result = keyPairGenerator.generateKeyPair().getPrivate(); } else { Assert.fail("Unsupported key algorithm: " + originalPrivateKey.getAlgorithm()); result = null; diff --git a/support/src/test/java/libcore/javax/net/ssl/TestSSLContext.java b/support/src/test/java/libcore/javax/net/ssl/TestSSLContext.java index 64c8ccb..9793d9a 100644 --- a/support/src/test/java/libcore/javax/net/ssl/TestSSLContext.java +++ b/support/src/test/java/libcore/javax/net/ssl/TestSSLContext.java @@ -141,7 +141,7 @@ public final class TestSSLContext extends Assert { * TestSSLContext creation method that allows separate creation of server key store */ public static TestSSLContext create(TestKeyStore client, TestKeyStore server) { - String protocol = "TLS"; + String protocol = "TLSv1.2"; SSLContext clientContext = createSSLContext(protocol, client.keyManagers, client.trustManagers); SSLContext serverContext = diff --git a/support/src/test/java/libcore/javax/net/ssl/TestSSLEnginePair.java b/support/src/test/java/libcore/javax/net/ssl/TestSSLEnginePair.java index b6efdeb..79d5d00 100644 --- a/support/src/test/java/libcore/javax/net/ssl/TestSSLEnginePair.java +++ b/support/src/test/java/libcore/javax/net/ssl/TestSSLEnginePair.java @@ -47,10 +47,19 @@ public final class TestSSLEnginePair extends Assert { } public static TestSSLEnginePair create(TestSSLContext c, Hooks hooks) throws IOException { - SSLEngine[] engines = connect(c, hooks); + return create(c, hooks, null); + } + + public static TestSSLEnginePair create(TestSSLContext c, Hooks hooks, boolean[] finished) + throws IOException { + SSLEngine[] engines = connect(c, hooks, finished); return new TestSSLEnginePair(c, engines[0], engines[1]); } + public static SSLEngine[] connect(TestSSLContext c, Hooks hooks) throws IOException { + return connect(c, hooks, null); + } + /** * Create a new connected server/client engine pair within a * existing SSLContext. Optionally specify clientCipherSuites to @@ -59,11 +68,16 @@ public final class TestSSLEnginePair extends Assert { * cipher suite negotiation. */ public static SSLEngine[] connect(final TestSSLContext c, - Hooks hooks) throws IOException { + Hooks hooks, + boolean finished[]) throws IOException { if (hooks == null) { hooks = new Hooks(); } + // FINISHED state should be returned only once. + boolean[] clientFinished = new boolean[1]; + boolean[] serverFinished = new boolean[1]; + SSLSession session = c.clientContext.createSSLEngine().getSession(); int packetBufferSize = session.getPacketBufferSize(); @@ -73,7 +87,7 @@ public final class TestSSLEnginePair extends Assert { int applicationBufferSize = session.getApplicationBufferSize(); ByteBuffer scratch = ByteBuffer.allocate(applicationBufferSize); - SSLEngine client = c.clientContext.createSSLEngine(); + SSLEngine client = c.clientContext.createSSLEngine(c.host.getHostName(), c.port); SSLEngine server = c.serverContext.createSSLEngine(); client.setUseClientMode(true); server.setUseClientMode(false); @@ -93,20 +107,26 @@ public final class TestSSLEnginePair extends Assert { progress |= handshakeCompleted(client, clientToServer, serverToClient, - scratch); + scratch, + clientFinished); } if (!serverDone) { progress |= handshakeCompleted(server, serverToClient, clientToServer, - scratch); + scratch, + serverFinished); } if (!progress) { - // let caller detect the problem, but don't just hang here break; } } + if (finished != null) { + assertEquals(2, finished.length); + finished[0] = clientFinished[0]; + finished[1] = clientFinished[0]; + } return new SSLEngine[] { server, client }; } @@ -119,7 +139,8 @@ public final class TestSSLEnginePair extends Assert { private static boolean handshakeCompleted(SSLEngine engine, ByteBuffer output, ByteBuffer input, - ByteBuffer scratch) throws IOException { + ByteBuffer scratch, + boolean[] finished) throws IOException { try { // make the other side's output into our input input.flip(); @@ -127,7 +148,7 @@ public final class TestSSLEnginePair extends Assert { HandshakeStatus status = engine.getHandshakeStatus(); switch (status) { - case NEED_TASK: + case NEED_TASK: { boolean progress = false; while (true) { Runnable runnable = engine.getDelegatedTask(); @@ -137,8 +158,9 @@ public final class TestSSLEnginePair extends Assert { runnable.run(); progress = true; } + } - case NEED_UNWRAP: + case NEED_UNWRAP: { // avoid underflow if (input.remaining() == 0) { return false; @@ -146,16 +168,20 @@ public final class TestSSLEnginePair extends Assert { SSLEngineResult unwrapResult = engine.unwrap(input, scratch); assertEquals(SSLEngineResult.Status.OK, unwrapResult.getStatus()); assertEquals(0, scratch.position()); + assertFinishedOnce(finished, unwrapResult); return true; + } - case NEED_WRAP: + case NEED_WRAP: { // avoid possible overflow if (output.remaining() != output.capacity()) { return false; } SSLEngineResult wrapResult = engine.wrap(EMPTY_BYTE_BUFFER, output); assertEquals(SSLEngineResult.Status.OK, wrapResult.getStatus()); + assertFinishedOnce(finished, wrapResult); return true; + } case NOT_HANDSHAKING: // should have been checked by caller before calling @@ -170,4 +196,11 @@ public final class TestSSLEnginePair extends Assert { input.compact(); } } + + private static void assertFinishedOnce(boolean[] finishedOut, SSLEngineResult result) { + if (result.getHandshakeStatus() == HandshakeStatus.FINISHED) { + assertFalse("should only return FINISHED once", finishedOut[0]); + finishedOut[0] = true; + } + } } |