| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package libcore.javax.net.ssl; |
| |
| import java.security.InvalidAlgorithmParameterException; |
| import java.security.KeyStore; |
| import java.security.KeyStore.PrivateKeyEntry; |
| import java.security.Provider; |
| import java.security.Security; |
| import java.security.cert.CertificateException; |
| import java.security.cert.PKIXBuilderParameters; |
| import java.security.cert.PKIXParameters; |
| import java.security.cert.X509CertSelector; |
| import java.security.cert.X509Certificate; |
| import java.util.Set; |
| import javax.net.ssl.CertPathTrustManagerParameters; |
| import javax.net.ssl.ManagerFactoryParameters; |
| import javax.net.ssl.TrustManager; |
| import javax.net.ssl.TrustManagerFactory; |
| import javax.net.ssl.X509TrustManager; |
| import junit.framework.TestCase; |
| import libcore.java.security.StandardNames; |
| import libcore.java.security.TestKeyStore; |
| |
| public class TrustManagerFactoryTest extends TestCase { |
| |
| private static final String [] KEY_TYPES = new String[] { "RSA", "DSA", "EC", "EC_RSA" }; |
| |
| private static TestKeyStore TEST_KEY_STORE; |
| |
| // note the rare usage of DSA keys here in addition to RSA |
| private static TestKeyStore getTestKeyStore() throws Exception { |
| if (TEST_KEY_STORE == null) { |
| TEST_KEY_STORE = new TestKeyStore.Builder() |
| .keyAlgorithms(KEY_TYPES) |
| .aliasPrefix("rsa-dsa-ec") |
| .build(); |
| } |
| return TEST_KEY_STORE; |
| } |
| |
| private static boolean supportsManagerFactoryParameters(String algorithm) { |
| return (StandardNames.IS_RI && algorithm.equals("PKIX")); |
| } |
| |
| public void test_TrustManagerFactory_getDefaultAlgorithm() throws Exception { |
| String algorithm = TrustManagerFactory.getDefaultAlgorithm(); |
| assertEquals(StandardNames.TRUST_MANAGER_FACTORY_DEFAULT, algorithm); |
| TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm); |
| test_TrustManagerFactory(tmf); |
| } |
| |
| private static class UselessManagerFactoryParameters implements ManagerFactoryParameters {} |
| |
| private void test_TrustManagerFactory(TrustManagerFactory tmf) |
| throws Exception { |
| assertNotNull(tmf); |
| assertNotNull(tmf.getAlgorithm()); |
| assertNotNull(tmf.getProvider()); |
| |
| // before init |
| try { |
| tmf.getTrustManagers(); |
| fail(); |
| } catch (IllegalStateException expected) { |
| } |
| |
| // init with null ManagerFactoryParameters |
| try { |
| tmf.init((ManagerFactoryParameters) null); |
| fail(); |
| } catch (InvalidAlgorithmParameterException expected) { |
| } |
| |
| // init with useless ManagerFactoryParameters |
| try { |
| tmf.init(new UselessManagerFactoryParameters()); |
| fail(); |
| } catch (InvalidAlgorithmParameterException expected) { |
| } |
| |
| // init with PKIXParameters ManagerFactoryParameters |
| try { |
| PKIXParameters pp = new PKIXParameters(getTestKeyStore().keyStore); |
| CertPathTrustManagerParameters cptmp = new CertPathTrustManagerParameters(pp); |
| tmf.init(cptmp); |
| fail(); |
| } catch (InvalidAlgorithmParameterException expected) { |
| } |
| |
| // init with PKIXBuilderParameters ManagerFactoryParameters |
| X509CertSelector xcs = new X509CertSelector(); |
| PKIXBuilderParameters pbp = new PKIXBuilderParameters(getTestKeyStore().keyStore, xcs); |
| CertPathTrustManagerParameters cptmp = new CertPathTrustManagerParameters(pbp); |
| if (supportsManagerFactoryParameters(tmf.getAlgorithm())) { |
| tmf.init(cptmp); |
| test_TrustManagerFactory_getTrustManagers(tmf); |
| } else { |
| try { |
| tmf.init(cptmp); |
| fail(); |
| } catch (InvalidAlgorithmParameterException expected) { |
| } |
| } |
| |
| // init with null for default KeyStore |
| tmf.init((KeyStore) null); |
| test_TrustManagerFactory_getTrustManagers(tmf); |
| |
| // init with specific key store |
| tmf.init(getTestKeyStore().keyStore); |
| test_TrustManagerFactory_getTrustManagers(tmf); |
| } |
| |
| private void test_TrustManagerFactory_getTrustManagers(TrustManagerFactory tmf) |
| throws Exception { |
| TrustManager[] trustManagers = tmf.getTrustManagers(); |
| assertNotNull(trustManagers); |
| assertTrue(trustManagers.length > 0); |
| for (TrustManager trustManager : trustManagers) { |
| assertNotNull(trustManager); |
| if (trustManager instanceof X509TrustManager) { |
| test_X509TrustManager((X509TrustManager) trustManager); |
| } |
| } |
| } |
| |
| private void test_X509TrustManager(X509TrustManager tm) throws Exception { |
| for (String keyType : KEY_TYPES) { |
| X509Certificate[] issuers = tm.getAcceptedIssuers(); |
| assertNotNull(issuers); |
| assertTrue(issuers.length > 1); |
| assertNotSame(issuers, tm.getAcceptedIssuers()); |
| boolean defaultTrustManager |
| // RI de-duplicates certs from TrustedCertificateEntry and PrivateKeyEntry |
| = issuers.length > (StandardNames.IS_RI ? 1 : 2) * KEY_TYPES.length; |
| |
| String keyAlgName = TestKeyStore.keyAlgorithm(keyType); |
| String sigAlgName = TestKeyStore.signatureAlgorithm(keyType); |
| PrivateKeyEntry pke = getTestKeyStore().getPrivateKey(keyAlgName, sigAlgName); |
| X509Certificate[] chain = (X509Certificate[]) pke.getCertificateChain(); |
| if (defaultTrustManager) { |
| try { |
| tm.checkClientTrusted(chain, keyType); |
| fail(); |
| } catch (CertificateException expected) { |
| } |
| try { |
| tm.checkServerTrusted(chain, keyType); |
| fail(); |
| } catch (CertificateException expected) { |
| } |
| } else { |
| tm.checkClientTrusted(chain, keyType); |
| tm.checkServerTrusted(chain, keyType); |
| } |
| |
| } |
| } |
| |
| public void test_TrustManagerFactory_getInstance() throws Exception { |
| Provider[] providers = Security.getProviders(); |
| for (Provider provider : providers) { |
| Set<Provider.Service> services = provider.getServices(); |
| for (Provider.Service service : services) { |
| String type = service.getType(); |
| if (!type.equals("TrustManagerFactory")) { |
| continue; |
| } |
| String algorithm = service.getAlgorithm(); |
| { |
| TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm); |
| assertEquals(algorithm, tmf.getAlgorithm()); |
| test_TrustManagerFactory(tmf); |
| } |
| |
| { |
| TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm, |
| provider); |
| assertEquals(algorithm, tmf.getAlgorithm()); |
| assertEquals(provider, tmf.getProvider()); |
| test_TrustManagerFactory(tmf); |
| } |
| |
| { |
| TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm, |
| provider.getName()); |
| assertEquals(algorithm, tmf.getAlgorithm()); |
| assertEquals(provider, tmf.getProvider()); |
| test_TrustManagerFactory(tmf); |
| } |
| } |
| } |
| } |
| |
| public void test_TrustManagerFactory_intermediate() throws Exception { |
| // chain should be server/intermediate/root |
| PrivateKeyEntry pke = TestKeyStore.getServer().getPrivateKey("RSA", "RSA"); |
| X509Certificate[] chain = (X509Certificate[])pke.getCertificateChain(); |
| assertEquals(3, chain.length); |
| |
| // keyStore should contain only the intermediate CA so we can |
| // test proper validation even if there are extra certs after |
| // the trusted one (in this case the original root is "extra") |
| KeyStore keyStore = TestKeyStore.createKeyStore(); |
| keyStore.setCertificateEntry("alias", chain[1]); |
| |
| Provider[] providers = Security.getProviders(); |
| for (Provider provider : providers) { |
| Set<Provider.Service> services = provider.getServices(); |
| for (Provider.Service service : services) { |
| String type = service.getType(); |
| if (!type.equals("TrustManagerFactory")) { |
| continue; |
| } |
| String algorithm = service.getAlgorithm(); |
| TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm); |
| tmf.init(keyStore); |
| TrustManager[] trustManagers = tmf.getTrustManagers(); |
| for (TrustManager trustManager : trustManagers) { |
| if (!(trustManager instanceof X509TrustManager)) { |
| continue; |
| } |
| X509TrustManager tm = (X509TrustManager) trustManager; |
| tm.checkClientTrusted(chain, "RSA"); |
| tm.checkServerTrusted(chain, "RSA"); |
| } |
| } |
| } |
| } |
| |
| public void test_TrustManagerFactory_keyOnly() throws Exception { |
| // create a KeyStore containing only a private key with chain. |
| // unlike PKIXParameters(KeyStore), the cert chain of the key should be trusted. |
| KeyStore ks = TestKeyStore.createKeyStore(); |
| KeyStore.PrivateKeyEntry pke = getTestKeyStore().getPrivateKey("RSA", "RSA"); |
| ks.setKeyEntry("key", pke.getPrivateKey(), "pw".toCharArray(), pke.getCertificateChain()); |
| |
| String algorithm = TrustManagerFactory.getDefaultAlgorithm(); |
| TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm); |
| tmf.init(ks); |
| X509TrustManager trustManager = (X509TrustManager) tmf.getTrustManagers()[0]; |
| trustManager.checkServerTrusted((X509Certificate[]) pke.getCertificateChain(), "RSA"); |
| } |
| |
| } |