TestSSLContext.java revision 4e1404f2017dc7db05b69ecad241f78c5bb1a4ee
1bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom/*
2bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Copyright (C) 2010 The Android Open Source Project
3bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom *
4bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License");
5bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * you may not use this file except in compliance with the License.
6bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * You may obtain a copy of the License at
7bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom *
8bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom *      http://www.apache.org/licenses/LICENSE-2.0
9bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom *
10bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Unless required by applicable law or agreed to in writing, software
11bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS,
12bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * See the License for the specific language governing permissions and
14bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * limitations under the License.
15bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom */
16bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
174557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonpackage libcore.javax.net.ssl;
18bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
193258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstromimport java.io.IOException;
20bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstromimport java.net.InetAddress;
213258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstromimport java.net.Socket;
223258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstromimport java.net.UnknownHostException;
23bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstromimport java.security.KeyStore;
24204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstromimport java.security.Principal;
25bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstromimport java.security.SecureRandom;
26e688a4123f165ed2905878e312b074b8c825d119Brian Carlstromimport java.security.cert.Certificate;
27059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstromimport java.security.cert.CertificateException;
28bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstromimport java.security.cert.X509Certificate;
29204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstromimport java.util.Collections;
304557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport javax.net.ssl.KeyManager;
314557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport javax.net.ssl.SSLContext;
324557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport javax.net.ssl.SSLServerSocket;
333258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstromimport javax.net.ssl.SSLSocket;
343258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstromimport javax.net.ssl.SSLSocketFactory;
354557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport javax.net.ssl.TrustManager;
364557728efb66c455a52b7669a8eefef7a9e54854Jesse Wilsonimport javax.net.ssl.X509TrustManager;
370c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstromimport junit.framework.Assert;
383258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstromimport libcore.java.security.StandardNames;
393258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstromimport libcore.java.security.TestKeyStore;
40bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
41bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom/**
42bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * TestSSLContext is a convenience class for other tests that
43bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * want a canned SSLContext and related state for testing so they
44bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * don't have to duplicate the logic.
45bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom */
460c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrompublic final class TestSSLContext extends Assert {
47bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
48f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    /*
490af0a7959d838c48e6b4e8dc9ac188ff6bbb6a87Brian Carlstrom     * The RI and Android have very different default SSLSession cache behaviors.
500af0a7959d838c48e6b4e8dc9ac188ff6bbb6a87Brian Carlstrom     * The RI keeps an unlimited number of SSLSesions around for 1 day.
51f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * Android keeps 10 SSLSessions forever.
520af0a7959d838c48e6b4e8dc9ac188ff6bbb6a87Brian Carlstrom     */
539a106a63508697a6f5f02c20b7cc6b7c6152695fBrian Carlstrom    private static final boolean IS_RI = StandardNames.IS_RI;
540af0a7959d838c48e6b4e8dc9ac188ff6bbb6a87Brian Carlstrom    public static final int EXPECTED_DEFAULT_CLIENT_SSL_SESSION_CACHE_SIZE = (IS_RI) ? 0 : 10;
550af0a7959d838c48e6b4e8dc9ac188ff6bbb6a87Brian Carlstrom    public static final int EXPECTED_DEFAULT_SERVER_SSL_SESSION_CACHE_SIZE = (IS_RI) ? 0 : 100;
564e1404f2017dc7db05b69ecad241f78c5bb1a4eeAlex Klyubin    public static final int EXPECTED_DEFAULT_SSL_SESSION_CACHE_TIMEOUT =
574e1404f2017dc7db05b69ecad241f78c5bb1a4eeAlex Klyubin            (IS_RI) ? 24 * 3600 : 8 * 3600;
58bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
59bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    /**
60bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * The Android SSLSocket and SSLServerSocket implementations are
61bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * based on a version of OpenSSL which includes support for RFC
62bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * 4507 session tickets. When using session tickets, the server
63bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * does not need to keep a cache mapping session IDs to SSL
64bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * sessions for reuse. Instead, the client presents the server
65bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * with a session ticket it received from the server earlier,
66bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * which is an SSL session encrypted by the server's secret
67bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * key. Since in this case the server does not need to keep a
68bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * cache, some tests may find different results depending on
69bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * whether or not the session tickets are in use. These tests can
70bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * use this function to determine if loopback SSL connections are
71bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * expected to use session tickets and conditionalize their
72bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * results appropriately.
73bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     */
74bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    public static boolean sslServerSocketSupportsSessionTickets () {
750c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        // Disabled session tickets for better compatability b/2682876
760c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        // return !IS_RI;
770c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        return false;
78bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    }
79bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
80059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom    public final KeyStore clientKeyStore;
81e3a187163504f00c98bd75cbd8bcbdde123ae2cdBrian Carlstrom    public final char[] clientStorePassword;
82059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom    public final KeyStore serverKeyStore;
83e3a187163504f00c98bd75cbd8bcbdde123ae2cdBrian Carlstrom    public final char[] serverStorePassword;
84edeec21a9c9e97cad91dffd47d4f2f7185dffe07Alex Klyubin    public final KeyManager[] clientKeyManagers;
85edeec21a9c9e97cad91dffd47d4f2f7185dffe07Alex Klyubin    public final KeyManager[] serverKeyManagers;
8636214feb86a0963b23f34c8c63584252bd757e19Brian Carlstrom    public final X509TrustManager clientTrustManager;
8736214feb86a0963b23f34c8c63584252bd757e19Brian Carlstrom    public final X509TrustManager serverTrustManager;
88059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom    public final SSLContext clientContext;
89059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom    public final SSLContext serverContext;
90bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    public final SSLServerSocket serverSocket;
91bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    public final InetAddress host;
92bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    public final int port;
93bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
94059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom    private TestSSLContext(KeyStore clientKeyStore,
95e3a187163504f00c98bd75cbd8bcbdde123ae2cdBrian Carlstrom                           char[] clientStorePassword,
96059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                           KeyStore serverKeyStore,
97e3a187163504f00c98bd75cbd8bcbdde123ae2cdBrian Carlstrom                           char[] serverStorePassword,
98edeec21a9c9e97cad91dffd47d4f2f7185dffe07Alex Klyubin                           KeyManager[] clientKeyManagers,
99edeec21a9c9e97cad91dffd47d4f2f7185dffe07Alex Klyubin                           KeyManager[] serverKeyManagers,
10036214feb86a0963b23f34c8c63584252bd757e19Brian Carlstrom                           X509TrustManager clientTrustManager,
10136214feb86a0963b23f34c8c63584252bd757e19Brian Carlstrom                           X509TrustManager serverTrustManager,
102059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                           SSLContext clientContext,
103059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                           SSLContext serverContext,
104bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                           SSLServerSocket serverSocket,
105bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                           InetAddress host,
106bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                           int port) {
107059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        this.clientKeyStore = clientKeyStore;
108e3a187163504f00c98bd75cbd8bcbdde123ae2cdBrian Carlstrom        this.clientStorePassword = clientStorePassword;
109059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        this.serverKeyStore = serverKeyStore;
110e3a187163504f00c98bd75cbd8bcbdde123ae2cdBrian Carlstrom        this.serverStorePassword = serverStorePassword;
111edeec21a9c9e97cad91dffd47d4f2f7185dffe07Alex Klyubin        this.clientKeyManagers = clientKeyManagers;
112edeec21a9c9e97cad91dffd47d4f2f7185dffe07Alex Klyubin        this.serverKeyManagers = serverKeyManagers;
113059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        this.clientTrustManager = clientTrustManager;
114059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        this.serverTrustManager = serverTrustManager;
115059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        this.clientContext = clientContext;
116059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        this.serverContext = serverContext;
117bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        this.serverSocket = serverSocket;
118bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        this.host = host;
119bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        this.port = port;
120bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    }
121bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
122f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom    public void close() {
123f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        try {
124f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            serverSocket.close();
125f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        } catch (Exception e) {
126f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom            throw new RuntimeException(e);
127f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom        }
128f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom    }
129f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom
130e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom    /**
131e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom     * Usual TestSSLContext creation method, creates underlying
132e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom     * SSLContext with certificate and key as well as SSLServerSocket
133e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom     * listening provided host and port.
134e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom     */
135bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    public static TestSSLContext create() {
136059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        return create(TestKeyStore.getClient(),
137059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                      TestKeyStore.getServer());
138bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    }
139bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
140e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom    /**
141059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom     * TestSSLContext creation method that allows separate creation of server key store
142e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom     */
143059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom    public static TestSSLContext create(TestKeyStore client, TestKeyStore server) {
144c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin        return createWithAdditionalKeyManagers(client, server, null, null);
145c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin    }
146c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin
147c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin    /**
148c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin     * TestSSLContext creation method that allows separate creation of server key store and
149c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin     * the use of additional {@code KeyManager} instances
150c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin     */
151c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin    public static TestSSLContext createWithAdditionalKeyManagers(
152c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin            TestKeyStore client, TestKeyStore server,
153c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin            KeyManager[] additionalClientKeyManagers, KeyManager[] additionalServerKeyManagers) {
1543ad1704dc8e4653f4ceaeb5d8315ddb28318a1bbKenny Root        String protocol = "TLSv1.2";
155c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin        KeyManager[] clientKeyManagers = concat(client.keyManagers, additionalClientKeyManagers);
156c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin        KeyManager[] serverKeyManagers = concat(server.keyManagers, additionalServerKeyManagers);
1572cca77af136c57106bd9a1652e54a0ee99154d89Alex Klyubin        SSLContext clientContext =
158c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin                createSSLContext(protocol, clientKeyManagers, client.trustManagers);
1592cca77af136c57106bd9a1652e54a0ee99154d89Alex Klyubin        SSLContext serverContext =
160c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin                createSSLContext(protocol, serverKeyManagers, server.trustManagers);
161e3a187163504f00c98bd75cbd8bcbdde123ae2cdBrian Carlstrom        return create(client.keyStore, client.storePassword,
1626882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom                      server.keyStore, server.storePassword,
163c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin                      clientKeyManagers,
164c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin                      serverKeyManagers,
1656882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom                      client.trustManagers[0],
1666882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom                      server.trustManagers[0],
1676882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom                      clientContext,
1686882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom                      serverContext);
169bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    }
170bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
171bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    /**
172059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom     * TestSSLContext creation method that allows separate creation of client and server key store
173e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom     */
174e3a187163504f00c98bd75cbd8bcbdde123ae2cdBrian Carlstrom    public static TestSSLContext create(KeyStore clientKeyStore, char[] clientStorePassword,
1756882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom                                        KeyStore serverKeyStore, char[] serverStorePassword,
176edeec21a9c9e97cad91dffd47d4f2f7185dffe07Alex Klyubin                                        KeyManager[] clientKeyManagers,
177edeec21a9c9e97cad91dffd47d4f2f7185dffe07Alex Klyubin                                        KeyManager[] serverKeyManagers,
1786882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom                                        TrustManager clientTrustManagers,
1796882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom                                        TrustManager serverTrustManagers,
1806882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom                                        SSLContext clientContext,
1816882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom                                        SSLContext serverContext) {
182e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom        try {
183059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom            SSLServerSocket serverSocket = (SSLServerSocket)
184059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                serverContext.getServerSocketFactory().createServerSocket(0);
185547450702efd233213f953ba2213bb38803c34c3Jesse Wilson            InetAddress host = InetAddress.getLocalHost();
186547450702efd233213f953ba2213bb38803c34c3Jesse Wilson            int port = serverSocket.getLocalPort();
187e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom
188e3a187163504f00c98bd75cbd8bcbdde123ae2cdBrian Carlstrom            return new TestSSLContext(clientKeyStore, clientStorePassword,
189e3a187163504f00c98bd75cbd8bcbdde123ae2cdBrian Carlstrom                                      serverKeyStore, serverStorePassword,
190edeec21a9c9e97cad91dffd47d4f2f7185dffe07Alex Klyubin                                      clientKeyManagers,
191edeec21a9c9e97cad91dffd47d4f2f7185dffe07Alex Klyubin                                      serverKeyManagers,
19236214feb86a0963b23f34c8c63584252bd757e19Brian Carlstrom                                      (X509TrustManager) clientTrustManagers,
19336214feb86a0963b23f34c8c63584252bd757e19Brian Carlstrom                                      (X509TrustManager) serverTrustManagers,
194059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                                      clientContext, serverContext,
195059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                                      serverSocket, host, port);
196e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom        } catch (RuntimeException e) {
197e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom            throw e;
198e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom        } catch (Exception e) {
199e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom            throw new RuntimeException(e);
200e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom        }
201e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom    }
202e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom
203e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom    /**
204bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * Create a SSLContext with a KeyManager using the private key and
205bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * certificate chain from the given KeyStore and a TrustManager
206bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * using the certificates authorities from the same KeyStore.
207bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     */
2086882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom    public static final SSLContext createSSLContext(final String protocol,
2096882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom                                                    final KeyManager[] keyManagers,
210059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                                                    final TrustManager[] trustManagers)
2116882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom    {
2126882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom        try {
2132cca77af136c57106bd9a1652e54a0ee99154d89Alex Klyubin            SSLContext context = SSLContext.getInstance(protocol);
2146882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom            context.init(keyManagers, trustManagers, new SecureRandom());
2156882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom            return context;
2166882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom        } catch (Exception e) {
2176882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom            throw new RuntimeException(e);
2186882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom        }
219bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    }
220204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom
221204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom    public static void assertCertificateInKeyStore(Principal principal,
222204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom                                                   KeyStore keyStore) throws Exception {
223204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom        String subjectName = principal.getName();
224204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom        boolean found = false;
225204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom        for (String alias: Collections.list(keyStore.aliases())) {
226204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom            if (!keyStore.isCertificateEntry(alias)) {
227204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom                continue;
228204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom            }
229204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom            X509Certificate keyStoreCertificate = (X509Certificate) keyStore.getCertificate(alias);
230204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom            if (subjectName.equals(keyStoreCertificate.getSubjectDN().getName())) {
231204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom                found = true;
232204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom                break;
233204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom            }
234204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom        }
2350c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        assertTrue(found);
236204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom    }
237204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom
238204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom    public static void assertCertificateInKeyStore(Certificate certificate,
239204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom                                                   KeyStore keyStore) throws Exception {
240204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom        boolean found = false;
241204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom        for (String alias: Collections.list(keyStore.aliases())) {
242204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom            if (!keyStore.isCertificateEntry(alias)) {
243204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom                continue;
244204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom            }
245204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom            Certificate keyStoreCertificate = keyStore.getCertificate(alias);
246204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom            if (certificate.equals(keyStoreCertificate)) {
247204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom                found = true;
248204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom                break;
249204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom            }
250204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom        }
2510c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        assertTrue(found);
252204cab3c22b4d75c866c95e2d2eec42e14cbd924Brian Carlstrom    }
253059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom
254059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom    public static void assertServerCertificateChain(X509TrustManager trustManager,
255059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                                                    Certificate[] serverChain)
256059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom            throws CertificateException {
257059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        X509Certificate[] chain = (X509Certificate[]) serverChain;
258059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        trustManager.checkServerTrusted(chain, chain[0].getPublicKey().getAlgorithm());
259059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom    }
260059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom
261059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom    public static void assertClientCertificateChain(X509TrustManager trustManager,
262059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                                                    Certificate[] clientChain)
263059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom            throws CertificateException {
264059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        X509Certificate[] chain = (X509Certificate[]) clientChain;
265059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        trustManager.checkClientTrusted(chain, chain[0].getPublicKey().getAlgorithm());
266059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom    }
2673258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom
2683258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom    /**
2693258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom     * Returns an SSLSocketFactory that calls setWantClientAuth and
2703258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom     * setNeedClientAuth as specified on all returned sockets.
2713258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom     */
2723258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom    public static SSLSocketFactory clientAuth(final SSLSocketFactory sf,
2733258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom                                              final boolean want,
2743258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom                                              final boolean need) {
2753258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom        return new SSLSocketFactory() {
2763258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom            private SSLSocket set(Socket socket) {
2773258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom                SSLSocket s = (SSLSocket) socket;
2783258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom                s.setWantClientAuth(want);
2793258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom                s.setNeedClientAuth(need);
2803258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom                return s;
2813258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom            }
2823258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom            public Socket createSocket(String host, int port)
2833258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom                    throws IOException, UnknownHostException {
2843258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom                return set(sf.createSocket(host, port));
2853258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom            }
2863258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom            public Socket createSocket(String host, int port, InetAddress localHost, int localPort)
2873258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom                    throws IOException, UnknownHostException {
2883258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom                return set(sf.createSocket(host, port, localHost, localPort));
2893258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom            }
2903258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom            public Socket createSocket(InetAddress host, int port) throws IOException {
2913258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom                return set(sf.createSocket(host, port));
2923258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom            }
2933258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom            public Socket createSocket(InetAddress address, int port,
2943258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom                                       InetAddress localAddress, int localPort) throws IOException {
2953258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom                return set(sf.createSocket(address, port));
2963258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom            }
2973258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom
2983258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom            public String[] getDefaultCipherSuites() {
2993258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom                return sf.getDefaultCipherSuites();
3003258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom            }
3013258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom            public String[] getSupportedCipherSuites() {
3023258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom                return sf.getSupportedCipherSuites();
3033258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom            }
3043258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom
3053258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom            public Socket createSocket(Socket s, String host, int port, boolean autoClose)
3063258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom                    throws IOException {
3073258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom                return set(sf.createSocket(s, host, port, autoClose));
3083258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom            }
3093258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom        };
3103258b52429c7768ea91bda93c5a15257cdd390e5Brian Carlstrom    }
311c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin
312c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin    private static KeyManager[] concat(KeyManager[] a, KeyManager[] b) {
313c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin        if ((a == null) || (a.length == 0)) {
314c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin            return b;
315c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin        }
316c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin        if ((b == null) || (b.length == 0)) {
317c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin            return a;
318c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin        }
319c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin        KeyManager[] result = new KeyManager[a.length + b.length];
320c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin        System.arraycopy(a, 0, result, 0, a.length);
321c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin        System.arraycopy(b, 0, result, a.length, b.length);
322c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin        return result;
323c9461f39290f815f560f2ec50e9ccde5ff4eb8f7Alex Klyubin    }
324bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom}
325