package org.bouncycastle.jsse.provider.test; import java.security.SecureRandom; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLServerSocketFactory; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManagerFactory; import junit.framework.TestCase; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider; import org.bouncycastle.util.Arrays; public class CipherSuitesTestCase extends TestCase { protected final CipherSuitesTestConfig config; public CipherSuitesTestCase(String name) { super(name); this.config = null; } public CipherSuitesTestCase(CipherSuitesTestConfig config) { super(config.cipherSuite); this.config = config; } public void testDummy() { // Avoid "No tests found" warning from junit } protected void runTest() throws Throwable { // Disable the test if it is not being run via CipherSuitesTestSuite if (config == null) { return; } int port = PORT_NO.incrementAndGet(); SimpleServer server = new SimpleServer(port, config); SimpleClient client = new SimpleClient(port, config); TestProtocolUtil.runClientAndServer(server, client); TestCase.assertNotNull(server.tlsUnique); TestCase.assertNotNull(client.tlsUnique); TestCase.assertTrue(Arrays.areEqual(server.tlsUnique, client.tlsUnique)); } private static final String HOST = "localhost"; private static final AtomicInteger PORT_NO = new AtomicInteger(9100); static class SimpleClient implements TestProtocolUtil.BlockingCallable { private final int port; private final CipherSuitesTestConfig config; private final CountDownLatch latch; private byte[] tlsUnique = null; SimpleClient(int port, CipherSuitesTestConfig config) { this.port = port; this.config = config; this.latch = new CountDownLatch(1); } public Exception call() throws Exception { try { TrustManagerFactory trustMgrFact = TrustManagerFactory.getInstance("PKIX", BouncyCastleJsseProvider.PROVIDER_NAME); trustMgrFact.init(config.clientTrustStore); SSLContext clientContext = SSLContext.getInstance("TLS", BouncyCastleJsseProvider.PROVIDER_NAME); clientContext.init(null, trustMgrFact.getTrustManagers(), SecureRandom.getInstance("DEFAULT", BouncyCastleProvider.PROVIDER_NAME)); SSLSocketFactory fact = clientContext.getSocketFactory(); SSLSocket cSock = (SSLSocket)fact.createSocket(HOST, port); cSock.setEnabledCipherSuites(new String[]{ config.cipherSuite }); this.tlsUnique = TestUtils.getChannelBinding(cSock, "tls-unique"); TestProtocolUtil.doClientProtocol(cSock, "Hello"); } finally { latch.countDown(); } return null; } public void await() throws InterruptedException { latch.await(); } } static class SimpleServer implements TestProtocolUtil.BlockingCallable { private final int port; private final CipherSuitesTestConfig config; private final CountDownLatch latch; private byte[] tlsUnique = null; SimpleServer(int port, CipherSuitesTestConfig config) { this.port = port; this.config = config; this.latch = new CountDownLatch(1); } public Exception call() throws Exception { try { KeyManagerFactory keyMgrFact = KeyManagerFactory.getInstance("PKIX", BouncyCastleJsseProvider.PROVIDER_NAME); keyMgrFact.init(config.serverKeyStore, config.serverPassword); SSLContext serverContext = SSLContext.getInstance("TLS", BouncyCastleJsseProvider.PROVIDER_NAME); serverContext.init(keyMgrFact.getKeyManagers(), null, SecureRandom.getInstance("DEFAULT", BouncyCastleProvider.PROVIDER_NAME)); SSLServerSocketFactory fact = serverContext.getServerSocketFactory(); SSLServerSocket sSock = (SSLServerSocket)fact.createServerSocket(port); sSock.setEnabledCipherSuites(new String[]{ config.cipherSuite }); latch.countDown(); SSLSocket sslSock = (SSLSocket)sSock.accept(); sslSock.setUseClientMode(false); this.tlsUnique = TestUtils.getChannelBinding(sslSock, "tls-unique"); TestProtocolUtil.doServerProtocol(sslSock, "World"); sslSock.close(); sSock.close(); } finally { latch.countDown(); } return null; } public void await() throws InterruptedException { latch.await(); } } }