package org.bouncycastle.jsse.provider.test; import java.io.IOException; import java.security.GeneralSecurityException; import java.security.KeyPair; import java.security.KeyStore; import java.security.SecureRandom; import java.security.Security; import java.security.cert.X509Certificate; import java.util.concurrent.CountDownLatch; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLServerSocketFactory; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManagerFactory; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider; import junit.framework.TestCase; public class BasicClientAuthTlsTest extends TestCase { protected void setUp() { if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) { Security.addProvider(new BouncyCastleProvider()); } if (Security.getProvider(BouncyCastleJsseProvider.PROVIDER_NAME) == null) { Security.addProvider(new BouncyCastleJsseProvider()); } } private static final String HOST = "localhost"; private static final int PORT_NO = 9020; public static class ClientAuthClient implements TestProtocolUtil.BlockingCallable { private final KeyStore trustStore; private final KeyStore clientStore; private final char[] clientKeyPass; private final CountDownLatch latch; public ClientAuthClient(KeyStore clientStore, char[] clientKeyPass, X509Certificate trustAnchor) throws GeneralSecurityException, IOException { this.trustStore = KeyStore.getInstance("JKS"); trustStore.load(null, null); trustStore.setCertificateEntry("server", trustAnchor); this.clientStore = clientStore; this.clientKeyPass = clientKeyPass; this.latch = new CountDownLatch(1); } public Exception call() throws Exception { try { TrustManagerFactory trustMgrFact = TrustManagerFactory.getInstance("PKIX", BouncyCastleJsseProvider.PROVIDER_NAME); trustMgrFact.init(trustStore); KeyManagerFactory keyMgrFact = KeyManagerFactory.getInstance("PKIX", BouncyCastleJsseProvider.PROVIDER_NAME); keyMgrFact.init(clientStore, clientKeyPass); SSLContext clientContext = SSLContext.getInstance("TLS", BouncyCastleJsseProvider.PROVIDER_NAME); clientContext.init(keyMgrFact.getKeyManagers(), trustMgrFact.getTrustManagers(), SecureRandom.getInstance("DEFAULT", BouncyCastleProvider.PROVIDER_NAME)); SSLSocketFactory fact = clientContext.getSocketFactory(); SSLSocket cSock = (SSLSocket)fact.createSocket(HOST, PORT_NO); SSLSession session = cSock.getSession(); assertNotNull(session.getCipherSuite()); assertEquals("CN=Test CA Certificate", session.getLocalPrincipal().getName()); assertEquals("CN=Test CA Certificate", session.getPeerPrincipal().getName()); TestProtocolUtil.doClientProtocol(cSock, "Hello"); } finally { latch.countDown(); } return null; } public void await() throws InterruptedException { latch.await(); } } public static class ClientAuthServer implements TestProtocolUtil.BlockingCallable { private final KeyStore serverStore; private final char[] keyPass; private final KeyStore trustStore; private final CountDownLatch latch; ClientAuthServer(KeyStore serverStore, char[] keyPass, X509Certificate trustAnchor) throws GeneralSecurityException, IOException { this.serverStore = serverStore; this.keyPass = keyPass; this.trustStore = KeyStore.getInstance("JKS"); trustStore.load(null, null); trustStore.setCertificateEntry("client", trustAnchor); this.latch = new CountDownLatch(1); } public Exception call() throws Exception { try { KeyManagerFactory keyMgrFact = KeyManagerFactory.getInstance("PKIX", BouncyCastleJsseProvider.PROVIDER_NAME); keyMgrFact.init(serverStore, keyPass); TrustManagerFactory trustMgrFact = TrustManagerFactory.getInstance("PKIX", BouncyCastleJsseProvider.PROVIDER_NAME); trustMgrFact.init(trustStore); SSLContext serverContext = SSLContext.getInstance("TLS", BouncyCastleJsseProvider.PROVIDER_NAME); serverContext.init(keyMgrFact.getKeyManagers(), trustMgrFact.getTrustManagers(), SecureRandom.getInstance("DEFAULT", BouncyCastleProvider.PROVIDER_NAME)); SSLServerSocketFactory fact = serverContext.getServerSocketFactory(); SSLServerSocket sSock = (SSLServerSocket)fact.createServerSocket(PORT_NO); SSLUtils.enableAll(sSock); sSock.setNeedClientAuth(true); latch.countDown(); SSLSocket sslSock = (SSLSocket)sSock.accept(); SSLSession session = sslSock.getSession(); assertNotNull(session.getCipherSuite()); assertEquals("CN=Test CA Certificate", session.getLocalPrincipal().getName()); assertEquals("CN=Test CA Certificate", session.getPeerPrincipal().getName()); TestProtocolUtil.doServerProtocol(sslSock, "World"); sslSock.close(); sSock.close(); } finally { latch.countDown(); } return null; } public void await() throws InterruptedException { latch.await(); } } public void testClientAuthTlsConnection() throws Exception { char[] keyPass = "keyPassword".toCharArray(); KeyPair caKeyPair = TestUtils.generateECKeyPair();; X509Certificate caCert = TestUtils.generateRootCert(caKeyPair); KeyStore serverKs = KeyStore.getInstance("JKS"); serverKs.load(null, null); serverKs.setKeyEntry("server", caKeyPair.getPrivate(), keyPass, new X509Certificate[]{ caCert }); KeyStore clientKs = KeyStore.getInstance("JKS"); clientKs.load(null, null); clientKs.setKeyEntry("client", caKeyPair.getPrivate(), keyPass, new X509Certificate[]{ caCert }); TestProtocolUtil.runClientAndServer(new ClientAuthServer(serverKs, keyPass, caCert), new ClientAuthClient(serverKs, keyPass, caCert)); } }