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