Home | History | Annotate | Download | only in ssl
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package libcore.javax.net.ssl;
     18 
     19 import java.net.InetAddress;
     20 import java.net.InetSocketAddress;
     21 import java.security.KeyStore;
     22 import java.security.Principal;
     23 import java.security.SecureRandom;
     24 import libcore.java.security.StandardNames;
     25 import libcore.java.security.TestKeyStore;
     26 import java.security.cert.Certificate;
     27 import java.security.cert.CertificateException;
     28 import java.security.cert.X509Certificate;
     29 import java.util.Collections;
     30 import javax.net.ssl.KeyManager;
     31 import javax.net.ssl.SSLContext;
     32 import javax.net.ssl.SSLServerSocket;
     33 import javax.net.ssl.TrustManager;
     34 import javax.net.ssl.X509ExtendedKeyManager;
     35 import javax.net.ssl.X509TrustManager;
     36 import junit.framework.Assert;
     37 
     38 /**
     39  * TestSSLContext is a convenience class for other tests that
     40  * want a canned SSLContext and related state for testing so they
     41  * don't have to duplicate the logic.
     42  */
     43 public final class TestSSLContext extends Assert {
     44 
     45     /*
     46      * The RI and Android have very different default SSLSession cache behaviors.
     47      * The RI keeps an unlimited number of SSLSesions around for 1 day.
     48      * Android keeps 10 SSLSessions forever.
     49      */
     50     private static final boolean IS_RI = StandardNames.IS_RI;
     51     public static final int EXPECTED_DEFAULT_CLIENT_SSL_SESSION_CACHE_SIZE = (IS_RI) ? 0 : 10;
     52     public static final int EXPECTED_DEFAULT_SERVER_SSL_SESSION_CACHE_SIZE = (IS_RI) ? 0 : 100;
     53     public static final int EXPECTED_DEFAULT_SSL_SESSION_CACHE_TIMEOUT = (IS_RI) ? 86400 : 0;
     54 
     55     /**
     56      * The Android SSLSocket and SSLServerSocket implementations are
     57      * based on a version of OpenSSL which includes support for RFC
     58      * 4507 session tickets. When using session tickets, the server
     59      * does not need to keep a cache mapping session IDs to SSL
     60      * sessions for reuse. Instead, the client presents the server
     61      * with a session ticket it received from the server earlier,
     62      * which is an SSL session encrypted by the server's secret
     63      * key. Since in this case the server does not need to keep a
     64      * cache, some tests may find different results depending on
     65      * whether or not the session tickets are in use. These tests can
     66      * use this function to determine if loopback SSL connections are
     67      * expected to use session tickets and conditionalize their
     68      * results appropriately.
     69      */
     70     public static boolean sslServerSocketSupportsSessionTickets () {
     71         // Disabled session tickets for better compatability b/2682876
     72         // return !IS_RI;
     73         return false;
     74     }
     75 
     76     public final KeyStore clientKeyStore;
     77     public final char[] clientStorePassword;
     78     public final KeyStore serverKeyStore;
     79     public final char[] serverStorePassword;
     80     public final X509ExtendedKeyManager clientKeyManager;
     81     public final X509ExtendedKeyManager serverKeyManager;
     82     public final X509TrustManager clientTrustManager;
     83     public final X509TrustManager serverTrustManager;
     84     public final SSLContext clientContext;
     85     public final SSLContext serverContext;
     86     public final SSLServerSocket serverSocket;
     87     public final InetAddress host;
     88     public final int port;
     89 
     90     private TestSSLContext(KeyStore clientKeyStore,
     91                            char[] clientStorePassword,
     92                            KeyStore serverKeyStore,
     93                            char[] serverStorePassword,
     94                            X509ExtendedKeyManager clientKeyManager,
     95                            X509ExtendedKeyManager serverKeyManager,
     96                            X509TrustManager clientTrustManager,
     97                            X509TrustManager serverTrustManager,
     98                            SSLContext clientContext,
     99                            SSLContext serverContext,
    100                            SSLServerSocket serverSocket,
    101                            InetAddress host,
    102                            int port) {
    103         this.clientKeyStore = clientKeyStore;
    104         this.clientStorePassword = clientStorePassword;
    105         this.serverKeyStore = serverKeyStore;
    106         this.serverStorePassword = serverStorePassword;
    107         this.clientKeyManager = clientKeyManager;
    108         this.serverKeyManager = serverKeyManager;
    109         this.clientTrustManager = clientTrustManager;
    110         this.serverTrustManager = serverTrustManager;
    111         this.clientContext = clientContext;
    112         this.serverContext = serverContext;
    113         this.serverSocket = serverSocket;
    114         this.host = host;
    115         this.port = port;
    116     }
    117 
    118     /**
    119      * Usual TestSSLContext creation method, creates underlying
    120      * SSLContext with certificate and key as well as SSLServerSocket
    121      * listening provided host and port.
    122      */
    123     public static TestSSLContext create() {
    124         return create(TestKeyStore.getClient(),
    125                       TestKeyStore.getServer());
    126     }
    127 
    128     /**
    129      * TestSSLContext creation method that allows separate creation of server key store
    130      */
    131     public static TestSSLContext create(TestKeyStore client, TestKeyStore server) {
    132         String provider = StandardNames.JSSE_PROVIDER_NAME;
    133         return create(client, server, provider, provider);
    134     }
    135     public static TestSSLContext create(TestKeyStore client, TestKeyStore server,
    136                                         String clientProvider, String serverProvider) {
    137         String protocol = "TLS";
    138         SSLContext clientContext = createSSLContext(protocol, clientProvider,
    139                                                     client.keyManagers, client.trustManagers);
    140         SSLContext serverContext = createSSLContext(protocol, serverProvider,
    141                                                     server.keyManagers, server.trustManagers);
    142         return create(client.keyStore, client.storePassword,
    143                       server.keyStore, server.storePassword,
    144                       client.keyManagers[0],
    145                       server.keyManagers[0],
    146                       client.trustManagers[0],
    147                       server.trustManagers[0],
    148                       clientContext,
    149                       serverContext);
    150     }
    151 
    152     /**
    153      * TestSSLContext creation method that allows separate creation of client and server key store
    154      */
    155     public static TestSSLContext create(KeyStore clientKeyStore, char[] clientStorePassword,
    156                                         KeyStore serverKeyStore, char[] serverStorePassword,
    157                                         KeyManager clientKeyManagers,
    158                                         KeyManager serverKeyManagers,
    159                                         TrustManager clientTrustManagers,
    160                                         TrustManager serverTrustManagers,
    161                                         SSLContext clientContext,
    162                                         SSLContext serverContext) {
    163         try {
    164             SSLServerSocket serverSocket = (SSLServerSocket)
    165                 serverContext.getServerSocketFactory().createServerSocket(0);
    166             InetSocketAddress sa = (InetSocketAddress) serverSocket.getLocalSocketAddress();
    167             InetAddress host = sa.getAddress();
    168             int port = sa.getPort();
    169 
    170             return new TestSSLContext(clientKeyStore, clientStorePassword,
    171                                       serverKeyStore, serverStorePassword,
    172                                       (X509ExtendedKeyManager) clientKeyManagers,
    173                                       (X509ExtendedKeyManager) serverKeyManagers,
    174                                       (X509TrustManager) clientTrustManagers,
    175                                       (X509TrustManager) serverTrustManagers,
    176                                       clientContext, serverContext,
    177                                       serverSocket, host, port);
    178         } catch (RuntimeException e) {
    179             throw e;
    180         } catch (Exception e) {
    181             throw new RuntimeException(e);
    182         }
    183     }
    184 
    185     /**
    186      * Create a SSLContext with a KeyManager using the private key and
    187      * certificate chain from the given KeyStore and a TrustManager
    188      * using the certificates authorities from the same KeyStore.
    189      */
    190     public static final SSLContext createSSLContext(final String protocol,
    191                                                     final String provider,
    192                                                     final KeyManager[] keyManagers,
    193                                                     final TrustManager[] trustManagers)
    194     {
    195         try {
    196             SSLContext context = SSLContext.getInstance(protocol, provider);
    197             context.init(keyManagers, trustManagers, new SecureRandom());
    198             return context;
    199         } catch (Exception e) {
    200             throw new RuntimeException(e);
    201         }
    202     }
    203 
    204     public static void assertCertificateInKeyStore(Principal principal,
    205                                                    KeyStore keyStore) throws Exception {
    206         String subjectName = principal.getName();
    207         boolean found = false;
    208         for (String alias: Collections.list(keyStore.aliases())) {
    209             if (!keyStore.isCertificateEntry(alias)) {
    210                 continue;
    211             }
    212             X509Certificate keyStoreCertificate = (X509Certificate) keyStore.getCertificate(alias);
    213             if (subjectName.equals(keyStoreCertificate.getSubjectDN().getName())) {
    214                 found = true;
    215                 break;
    216             }
    217         }
    218         assertTrue(found);
    219     }
    220 
    221     public static void assertCertificateInKeyStore(Certificate certificate,
    222                                                    KeyStore keyStore) throws Exception {
    223         boolean found = false;
    224         for (String alias: Collections.list(keyStore.aliases())) {
    225             if (!keyStore.isCertificateEntry(alias)) {
    226                 continue;
    227             }
    228             Certificate keyStoreCertificate = keyStore.getCertificate(alias);
    229             if (certificate.equals(keyStoreCertificate)) {
    230                 found = true;
    231                 break;
    232             }
    233         }
    234         assertTrue(found);
    235     }
    236 
    237     public static void assertServerCertificateChain(X509TrustManager trustManager,
    238                                                     Certificate[] serverChain)
    239             throws CertificateException {
    240         X509Certificate[] chain = (X509Certificate[]) serverChain;
    241         trustManager.checkServerTrusted(chain, chain[0].getPublicKey().getAlgorithm());
    242     }
    243 
    244     public static void assertClientCertificateChain(X509TrustManager trustManager,
    245                                                     Certificate[] clientChain)
    246             throws CertificateException {
    247         X509Certificate[] chain = (X509Certificate[]) clientChain;
    248         trustManager.checkClientTrusted(chain, chain[0].getPublicKey().getAlgorithm());
    249     }
    250 }
    251