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.security.InvalidAlgorithmParameterException;
     20 import java.security.KeyStore;
     21 import java.security.KeyStore.PrivateKeyEntry;
     22 import java.security.Provider;
     23 import java.security.Security;
     24 import java.security.cert.CertificateException;
     25 import java.security.cert.PKIXBuilderParameters;
     26 import java.security.cert.PKIXParameters;
     27 import java.security.cert.X509CertSelector;
     28 import java.security.cert.X509Certificate;
     29 import java.util.Set;
     30 import javax.net.ssl.CertPathTrustManagerParameters;
     31 import javax.net.ssl.ManagerFactoryParameters;
     32 import javax.net.ssl.TrustManager;
     33 import javax.net.ssl.TrustManagerFactory;
     34 import javax.net.ssl.X509TrustManager;
     35 import junit.framework.TestCase;
     36 import libcore.java.security.StandardNames;
     37 import libcore.java.security.TestKeyStore;
     38 
     39 public class TrustManagerFactoryTest extends TestCase {
     40 
     41     private static final String [] KEY_TYPES = new String[] { "RSA", "DSA", "EC", "EC_RSA" };
     42 
     43     private static TestKeyStore TEST_KEY_STORE;
     44 
     45     // note the rare usage of DSA keys here in addition to RSA
     46     private static TestKeyStore getTestKeyStore() throws Exception {
     47         if (TEST_KEY_STORE == null) {
     48             TEST_KEY_STORE = new TestKeyStore.Builder()
     49                     .keyAlgorithms(KEY_TYPES)
     50                     .aliasPrefix("rsa-dsa-ec")
     51                     .build();
     52         }
     53         return TEST_KEY_STORE;
     54     }
     55 
     56     public void test_TrustManagerFactory_getDefaultAlgorithm() throws Exception {
     57         String algorithm = TrustManagerFactory.getDefaultAlgorithm();
     58         assertEquals(StandardNames.TRUST_MANAGER_FACTORY_DEFAULT, algorithm);
     59         TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
     60         test_TrustManagerFactory(tmf, StandardNames.IS_RI);
     61     }
     62 
     63     private static class UselessManagerFactoryParameters implements ManagerFactoryParameters {}
     64 
     65     private void test_TrustManagerFactory(TrustManagerFactory tmf,
     66                                           boolean supportsManagerFactoryParameters)
     67             throws Exception {
     68         assertNotNull(tmf);
     69         assertNotNull(tmf.getAlgorithm());
     70         assertNotNull(tmf.getProvider());
     71 
     72         // before init
     73         try {
     74             tmf.getTrustManagers();
     75             fail();
     76         } catch (IllegalStateException expected) {
     77         }
     78 
     79         // init with null ManagerFactoryParameters
     80         try {
     81             tmf.init((ManagerFactoryParameters) null);
     82             fail();
     83         } catch (InvalidAlgorithmParameterException expected) {
     84         }
     85 
     86         // init with useless ManagerFactoryParameters
     87         try {
     88             tmf.init(new UselessManagerFactoryParameters());
     89             fail();
     90         } catch (InvalidAlgorithmParameterException expected) {
     91         }
     92 
     93         // init with PKIXParameters ManagerFactoryParameters
     94         try {
     95             PKIXParameters pp = new PKIXParameters(getTestKeyStore().keyStore);
     96             CertPathTrustManagerParameters cptmp = new CertPathTrustManagerParameters(pp);
     97             tmf.init(cptmp);
     98             fail();
     99         } catch (InvalidAlgorithmParameterException expected) {
    100         }
    101 
    102         // init with PKIXBuilderParameters ManagerFactoryParameters
    103         X509CertSelector xcs = new X509CertSelector();
    104         PKIXBuilderParameters pbp = new PKIXBuilderParameters(getTestKeyStore().keyStore, xcs);
    105         CertPathTrustManagerParameters cptmp = new CertPathTrustManagerParameters(pbp);
    106         if (supportsManagerFactoryParameters) {
    107             tmf.init(cptmp);
    108             test_TrustManagerFactory_getTrustManagers(tmf);
    109         } else {
    110             try {
    111                 tmf.init(cptmp);
    112                 fail();
    113             } catch (InvalidAlgorithmParameterException expected) {
    114             }
    115         }
    116 
    117         // init with null for default KeyStore
    118         tmf.init((KeyStore) null);
    119         test_TrustManagerFactory_getTrustManagers(tmf);
    120 
    121         // init with specific key store
    122         tmf.init(getTestKeyStore().keyStore);
    123         test_TrustManagerFactory_getTrustManagers(tmf);
    124     }
    125 
    126     private void test_TrustManagerFactory_getTrustManagers(TrustManagerFactory tmf)
    127             throws Exception {
    128         TrustManager[] trustManagers = tmf.getTrustManagers();
    129         assertNotNull(trustManagers);
    130         assertTrue(trustManagers.length > 0);
    131         for (TrustManager trustManager : trustManagers) {
    132             assertNotNull(trustManager);
    133             if (trustManager instanceof X509TrustManager) {
    134                 test_X509TrustManager((X509TrustManager) trustManager);
    135             }
    136         }
    137     }
    138 
    139     private void test_X509TrustManager(X509TrustManager tm) throws Exception {
    140         for (String keyType : KEY_TYPES) {
    141             X509Certificate[] issuers = tm.getAcceptedIssuers();
    142             assertNotNull(issuers);
    143             assertTrue(issuers.length > 1);
    144             assertNotSame(issuers, tm.getAcceptedIssuers());
    145             boolean defaultTrustManager
    146                     // RI de-duplicates certs from TrustedCertificateEntry and PrivateKeyEntry
    147                     = issuers.length > (StandardNames.IS_RI ? 1 : 2) * KEY_TYPES.length;
    148 
    149             String keyAlgName = TestKeyStore.keyAlgorithm(keyType);
    150             String sigAlgName = TestKeyStore.signatureAlgorithm(keyType);
    151             PrivateKeyEntry pke = getTestKeyStore().getPrivateKey(keyAlgName, sigAlgName);
    152             X509Certificate[] chain = (X509Certificate[]) pke.getCertificateChain();
    153             if (defaultTrustManager) {
    154                 try {
    155                     tm.checkClientTrusted(chain, keyType);
    156                     fail();
    157                 } catch (CertificateException expected) {
    158                 }
    159                 try {
    160                     tm.checkServerTrusted(chain, keyType);
    161                     fail();
    162                 } catch (CertificateException expected) {
    163                 }
    164             } else {
    165                 tm.checkClientTrusted(chain, keyType);
    166                 tm.checkServerTrusted(chain, keyType);
    167             }
    168 
    169         }
    170     }
    171 
    172     public void test_TrustManagerFactory_getInstance() throws Exception {
    173         Provider[] providers = Security.getProviders();
    174         for (Provider provider : providers) {
    175             Set<Provider.Service> services = provider.getServices();
    176             for (Provider.Service service : services) {
    177                 String type = service.getType();
    178                 if (!type.equals("TrustManagerFactory")) {
    179                     continue;
    180                 }
    181                 String algorithm = service.getAlgorithm();
    182                 boolean supportsManagerFactoryParameters = algorithm.equals("PKIX");
    183                 {
    184                     TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
    185                     assertEquals(algorithm, tmf.getAlgorithm());
    186                     test_TrustManagerFactory(tmf, supportsManagerFactoryParameters);
    187                 }
    188 
    189                 {
    190                     TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm,
    191                                                                           provider);
    192                     assertEquals(algorithm, tmf.getAlgorithm());
    193                     assertEquals(provider, tmf.getProvider());
    194                     test_TrustManagerFactory(tmf, supportsManagerFactoryParameters);
    195                 }
    196 
    197                 {
    198                     TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm,
    199                                                                           provider.getName());
    200                     assertEquals(algorithm, tmf.getAlgorithm());
    201                     assertEquals(provider, tmf.getProvider());
    202                     test_TrustManagerFactory(tmf, supportsManagerFactoryParameters);
    203                 }
    204             }
    205         }
    206     }
    207 
    208     public void test_TrustManagerFactory_intermediate() throws Exception {
    209         // chain should be server/intermediate/root
    210         PrivateKeyEntry pke = TestKeyStore.getServer().getPrivateKey("RSA", "RSA");
    211         X509Certificate[] chain = (X509Certificate[])pke.getCertificateChain();
    212         assertEquals(3, chain.length);
    213 
    214         // keyStore should contain only the intermediate CA so we can
    215         // test proper validation even if there are extra certs after
    216         // the trusted one (in this case the original root is "extra")
    217         KeyStore keyStore = TestKeyStore.createKeyStore();
    218         keyStore.setCertificateEntry("alias", chain[1]);
    219 
    220         Provider[] providers = Security.getProviders();
    221         for (Provider provider : providers) {
    222             Set<Provider.Service> services = provider.getServices();
    223             for (Provider.Service service : services) {
    224                 String type = service.getType();
    225                 if (!type.equals("TrustManagerFactory")) {
    226                     continue;
    227                 }
    228                 String algorithm = service.getAlgorithm();
    229                 TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
    230                 tmf.init(keyStore);
    231                 TrustManager[] trustManagers = tmf.getTrustManagers();
    232                 for (TrustManager trustManager : trustManagers) {
    233                     if (!(trustManager instanceof X509TrustManager)) {
    234                         continue;
    235                     }
    236                     X509TrustManager tm = (X509TrustManager) trustManager;
    237                     tm.checkClientTrusted(chain, "RSA");
    238                     tm.checkServerTrusted(chain, "RSA");
    239                 }
    240             }
    241         }
    242     }
    243 
    244     public void test_TrustManagerFactory_keyOnly() throws Exception {
    245         // create a KeyStore containing only a private key with chain.
    246         // unlike PKIXParameters(KeyStore), the cert chain of the key should be trusted.
    247         KeyStore ks = TestKeyStore.createKeyStore();
    248         KeyStore.PrivateKeyEntry pke = getTestKeyStore().getPrivateKey("RSA", "RSA");
    249         ks.setKeyEntry("key", pke.getPrivateKey(), "pw".toCharArray(), pke.getCertificateChain());
    250 
    251         String algorithm = TrustManagerFactory.getDefaultAlgorithm();
    252         TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
    253         tmf.init(ks);
    254         X509TrustManager trustManager = (X509TrustManager) tmf.getTrustManagers()[0];
    255         trustManager.checkServerTrusted((X509Certificate[]) pke.getCertificateChain(), "RSA");
    256     }
    257 
    258 }
    259