blob: 94558dbc412a06367343851847c86af46c447880 [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed 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 libcore.javax.net.ssl;
import dalvik.annotation.KnownFailure;
import libcore.java.security.StandardNames;
import libcore.java.security.TestKeyStore;
import java.util.Arrays;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSession;
import junit.framework.TestCase;
public class SSLEngineTest extends TestCase {
public void assertConnected(TestSSLEnginePair e) {
assertConnected(e.client, e.server);
}
public void assertNotConnected(TestSSLEnginePair e) {
assertNotConnected(e.client, e.server);
}
public void assertConnected(SSLEngine a, SSLEngine b) {
assertTrue(connected(a, b));
}
public void assertNotConnected(SSLEngine a, SSLEngine b) {
assertFalse(connected(a, b));
}
public boolean connected(SSLEngine a, SSLEngine b) {
return (a.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING
&& b.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING
&& a.getSession() != null
&& b.getSession() != null
&& !a.isInboundDone()
&& !b.isInboundDone()
&& !a.isOutboundDone()
&& !b.isOutboundDone());
}
public void test_SSLEngine_getSupportedCipherSuites_names() throws Exception {
TestSSLContext c = TestSSLContext.create();
SSLEngine e = c.clientContext.createSSLEngine();
String[] cipherSuites = e.getSupportedCipherSuites();
StandardNames.assertSupportedCipherSuites(StandardNames.CIPHER_SUITES, cipherSuites);
assertNotSame(cipherSuites, e.getSupportedCipherSuites());
}
@KnownFailure("No *_WITH_NULL_* ciphers work because of 'Invalid transformation: null'")
public void test_SSLEngine_getSupportedCipherSuites_connect() throws Exception {
// note the rare usage of DSA keys here in addition to RSA
TestKeyStore testKeyStore = TestKeyStore.create(new String[] { "RSA", "DSA" },
null,
null,
"rsa-dsa",
TestKeyStore.localhost(),
true,
null);
TestSSLContext c = TestSSLContext.create(testKeyStore, testKeyStore);
String[] cipherSuites = c.clientContext.createSSLEngine().getSupportedCipherSuites();
for (String cipherSuite : cipherSuites) {
/*
* 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;
}
// System.out.println("Trying to connect cipher suite " + cipherSuite);
final String[] cipherSuiteArray = new String[] { cipherSuite };
assertConnected(TestSSLEnginePair.create(c, new TestSSLEnginePair.Hooks() {
@Override
void beforeBeginHandshake(SSLEngine client, SSLEngine server) {
client.setEnabledCipherSuites(cipherSuiteArray);
server.setEnabledCipherSuites(cipherSuiteArray);
}
}));
}
}
public void test_SSLEngine_getEnabledCipherSuites() throws Exception {
TestSSLContext c = TestSSLContext.create();
SSLEngine e = c.clientContext.createSSLEngine();
String[] cipherSuites = e.getEnabledCipherSuites();
StandardNames.assertValidCipherSuites(StandardNames.CIPHER_SUITES, cipherSuites);
assertNotSame(cipherSuites, e.getEnabledCipherSuites());
}
public void test_SSLEngine_setEnabledCipherSuites() throws Exception {
TestSSLContext c = TestSSLContext.create();
SSLEngine e = c.clientContext.createSSLEngine();
try {
e.setEnabledCipherSuites(null);
fail();
} catch (IllegalArgumentException expected) {
}
try {
e.setEnabledCipherSuites(new String[1]);
fail();
} catch (IllegalArgumentException expected) {
}
try {
e.setEnabledCipherSuites(new String[] { "Bogus" } );
fail();
} catch (IllegalArgumentException expected) {
}
e.setEnabledCipherSuites(new String[0]);
e.setEnabledCipherSuites(e.getEnabledCipherSuites());
e.setEnabledCipherSuites(e.getSupportedCipherSuites());
}
public void test_SSLEngine_getSupportedProtocols() throws Exception {
TestSSLContext c = TestSSLContext.create();
SSLEngine e = c.clientContext.createSSLEngine();
String[] protocols = e.getSupportedProtocols();
StandardNames.assertSupportedProtocols(StandardNames.SSL_SOCKET_PROTOCOLS, protocols);
assertNotSame(protocols, e.getSupportedProtocols());
}
public void test_SSLEngine_getEnabledProtocols() throws Exception {
TestSSLContext c = TestSSLContext.create();
SSLEngine e = c.clientContext.createSSLEngine();
String[] protocols = e.getEnabledProtocols();
StandardNames.assertValidProtocols(StandardNames.SSL_SOCKET_PROTOCOLS, protocols);
assertNotSame(protocols, e.getEnabledProtocols());
}
public void test_SSLEngine_setEnabledProtocols() throws Exception {
TestSSLContext c = TestSSLContext.create();
SSLEngine e = c.clientContext.createSSLEngine();
try {
e.setEnabledProtocols(null);
fail();
} catch (IllegalArgumentException expected) {
}
try {
e.setEnabledProtocols(new String[1]);
fail();
} catch (IllegalArgumentException expected) {
}
try {
e.setEnabledProtocols(new String[] { "Bogus" } );
fail();
} catch (IllegalArgumentException expected) {
}
e.setEnabledProtocols(new String[0]);
e.setEnabledProtocols(e.getEnabledProtocols());
e.setEnabledProtocols(e.getSupportedProtocols());
}
public void test_SSLEngine_getSession() throws Exception {
TestSSLContext c = TestSSLContext.create();
SSLEngine e = c.clientContext.createSSLEngine();
SSLSession session = e.getSession();
assertNotNull(session);
assertFalse(session.isValid());
}
public void test_SSLEngine_beginHandshake() throws Exception {
TestSSLContext c = TestSSLContext.create();
try {
c.clientContext.createSSLEngine().beginHandshake();
fail();
} catch (IllegalStateException expected) {
}
assertConnected(TestSSLEnginePair.create(null));
}
@KnownFailure("NO SERVER CERTIFICATE FOUND")
public void test_SSLEngine_beginHandshake_noKeyStore() throws Exception {
TestSSLContext c = TestSSLContext.create(null, null, null, null, null, null, null, null,
SSLContext.getDefault(), SSLContext.getDefault());
try {
// TODO Fix KnownFailure AlertException "NO SERVER CERTIFICATE FOUND"
// ServerHandshakeImpl.selectSuite should not select a suite without a required cert
TestSSLEnginePair.connect(c, null);
fail();
} catch (SSLHandshakeException expected) {
}
}
public void test_SSLEngine_beginHandshake_noClientCertificate() throws Exception {
TestSSLContext c = TestSSLContext.create();
SSLEngine[] engines = TestSSLEnginePair.connect(c, null);
assertConnected(engines[0], engines[1]);
}
public void test_SSLEngine_getUseClientMode() throws Exception {
TestSSLContext c = TestSSLContext.create();
assertFalse(c.clientContext.createSSLEngine().getUseClientMode());
assertFalse(c.clientContext.createSSLEngine(null, -1).getUseClientMode());
}
@KnownFailure("SSLHandshakeException instead assertNotConnected")
public void test_SSLEngine_setUseClientMode() throws Exception {
// client is client, server is server
assertConnected(test_SSLEngine_setUseClientMode(true, false));
// client is server, server is client
assertConnected(test_SSLEngine_setUseClientMode(false, true));
// both are client
assertNotConnected(test_SSLEngine_setUseClientMode(true, true));
// both are server
assertNotConnected(test_SSLEngine_setUseClientMode(false, false));
}
public void test_SSLEngine_setUseClientMode_afterHandshake() throws Exception {
// can't set after handshake
TestSSLEnginePair pair = TestSSLEnginePair.create(null);
try {
pair.server.setUseClientMode(false);
fail();
} catch (IllegalArgumentException expected) {
}
try {
pair.client.setUseClientMode(false);
fail();
} catch (IllegalArgumentException expected) {
}
}
private TestSSLEnginePair test_SSLEngine_setUseClientMode(final boolean clientClientMode,
final boolean serverClientMode)
throws Exception {
TestSSLContext c;
if (!clientClientMode && serverClientMode) {
c = TestSSLContext.create(TestKeyStore.getServer(), TestKeyStore.getClient());
} else {
c = TestSSLContext.create();
}
return TestSSLEnginePair.create(c, new TestSSLEnginePair.Hooks() {
@Override
void beforeBeginHandshake(SSLEngine client, SSLEngine server) {
client.setUseClientMode(clientClientMode);
server.setUseClientMode(serverClientMode);
}
});
}
@KnownFailure("init - invalid private key")
public void test_SSLEngine_clientAuth() throws Exception {
TestSSLContext c = TestSSLContext.create();
SSLEngine e = c.clientContext.createSSLEngine();
assertFalse(e.getWantClientAuth());
assertFalse(e.getNeedClientAuth());
// confirm turning one on by itself
e.setWantClientAuth(true);
assertTrue(e.getWantClientAuth());
assertFalse(e.getNeedClientAuth());
// confirm turning setting on toggles the other
e.setNeedClientAuth(true);
assertFalse(e.getWantClientAuth());
assertTrue(e.getNeedClientAuth());
// confirm toggling back
e.setWantClientAuth(true);
assertTrue(e.getWantClientAuth());
assertFalse(e.getNeedClientAuth());
// TODO Fix KnownFailure "init - invalid private key"
TestSSLContext clientAuthContext
= TestSSLContext.create(TestKeyStore.getClientCertificate(),
TestKeyStore.getServer());
TestSSLEnginePair p = TestSSLEnginePair.create(clientAuthContext,
new TestSSLEnginePair.Hooks() {
@Override
void beforeBeginHandshake(SSLEngine client, SSLEngine server) {
server.setWantClientAuth(true);
}
});
assertConnected(p);
assertNotNull(p.client.getSession().getLocalCertificates());
TestKeyStore.assertChainLength(p.client.getSession().getLocalCertificates());
TestSSLContext.assertClientCertificateChain(clientAuthContext.clientTrustManager,
p.client.getSession().getLocalCertificates());
}
public void test_SSLEngine_getEnableSessionCreation() throws Exception {
TestSSLContext c = TestSSLContext.create();
SSLEngine e = c.clientContext.createSSLEngine();
assertTrue(e.getEnableSessionCreation());
}
@KnownFailure("SSLException instead assertNotConnected")
public void test_SSLEngine_setEnableSessionCreation_server() throws Exception {
TestSSLEnginePair p = TestSSLEnginePair.create(new TestSSLEnginePair.Hooks() {
@Override
void beforeBeginHandshake(SSLEngine client, SSLEngine server) {
server.setEnableSessionCreation(false);
}
});
assertNotConnected(p);
}
@KnownFailure("AlertException instead of SSLException")
public void test_SSLEngine_setEnableSessionCreation_client() throws Exception {
try {
TestSSLEnginePair.create(new TestSSLEnginePair.Hooks() {
@Override
void beforeBeginHandshake(SSLEngine client, SSLEngine server) {
client.setEnableSessionCreation(false);
}
});
fail();
} catch (SSLException expected) {
}
}
public void test_SSLEngine_getSSLParameters() throws Exception {
TestSSLContext c = TestSSLContext.create();
SSLEngine e = c.clientContext.createSSLEngine();
SSLParameters p = e.getSSLParameters();
assertNotNull(p);
String[] cipherSuites = p.getCipherSuites();
StandardNames.assertValidCipherSuites(StandardNames.CIPHER_SUITES, cipherSuites);
assertNotSame(cipherSuites, e.getEnabledCipherSuites());
assertEquals(Arrays.asList(cipherSuites), Arrays.asList(e.getEnabledCipherSuites()));
String[] protocols = p.getProtocols();
StandardNames.assertValidProtocols(StandardNames.SSL_SOCKET_PROTOCOLS, protocols);
assertNotSame(protocols, e.getEnabledProtocols());
assertEquals(Arrays.asList(protocols), Arrays.asList(e.getEnabledProtocols()));
assertEquals(p.getWantClientAuth(), e.getWantClientAuth());
assertEquals(p.getNeedClientAuth(), e.getNeedClientAuth());
}
public void test_SSLEngine_setSSLParameters() throws Exception {
TestSSLContext c = TestSSLContext.create();
SSLEngine e = c.clientContext.createSSLEngine();
String[] defaultCipherSuites = e.getEnabledCipherSuites();
String[] defaultProtocols = e.getEnabledProtocols();
String[] supportedCipherSuites = e.getSupportedCipherSuites();
String[] supportedProtocols = e.getSupportedProtocols();
{
SSLParameters p = new SSLParameters();
e.setSSLParameters(p);
assertEquals(Arrays.asList(defaultCipherSuites),
Arrays.asList(e.getEnabledCipherSuites()));
assertEquals(Arrays.asList(defaultProtocols),
Arrays.asList(e.getEnabledProtocols()));
}
{
SSLParameters p = new SSLParameters(supportedCipherSuites,
supportedProtocols);
e.setSSLParameters(p);
assertEquals(Arrays.asList(supportedCipherSuites),
Arrays.asList(e.getEnabledCipherSuites()));
assertEquals(Arrays.asList(supportedProtocols),
Arrays.asList(e.getEnabledProtocols()));
}
{
SSLParameters p = new SSLParameters();
p.setNeedClientAuth(true);
assertFalse(e.getNeedClientAuth());
assertFalse(e.getWantClientAuth());
e.setSSLParameters(p);
assertTrue(e.getNeedClientAuth());
assertFalse(e.getWantClientAuth());
p.setWantClientAuth(true);
assertTrue(e.getNeedClientAuth());
assertFalse(e.getWantClientAuth());
e.setSSLParameters(p);
assertFalse(e.getNeedClientAuth());
assertTrue(e.getWantClientAuth());
p.setWantClientAuth(false);
assertFalse(e.getNeedClientAuth());
assertTrue(e.getWantClientAuth());
e.setSSLParameters(p);
assertFalse(e.getNeedClientAuth());
assertFalse(e.getWantClientAuth());
}
}
public void test_TestSSLEnginePair_create() throws Exception {
TestSSLEnginePair test = TestSSLEnginePair.create(null);
assertNotNull(test.c);
assertNotNull(test.server);
assertNotNull(test.client);
assertConnected(test);
}
}