TrustManagerImplTest.java revision d2cced8b10f5e4f600a5eb9464eba0da7c8f09de
1860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root/*
2860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root * Copyright (C) 2011 The Android Open Source Project
3860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root *
4860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root * Licensed under the Apache License, Version 2.0 (the "License");
5860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root * you may not use this file except in compliance with the License.
6860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root * You may obtain a copy of the License at
7860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root *
8860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root *      http://www.apache.org/licenses/LICENSE-2.0
9860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root *
10860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root * Unless required by applicable law or agreed to in writing, software
11860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root * distributed under the License is distributed on an "AS IS" BASIS,
12860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root * See the License for the specific language governing permissions and
14860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root * limitations under the License.
15860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root */
16860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
17860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootpackage org.conscrypt;
18860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
19860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.io.File;
20860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.io.FileWriter;
21d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Rootimport java.security.cert.Certificate;
22860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.security.cert.CertificateException;
23860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.security.cert.X509Certificate;
24860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.security.KeyStore;
25860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.security.MessageDigest;
26d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Rootimport java.security.Principal;
27860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.util.ArrayList;
28860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.util.Arrays;
29860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.util.List;
30d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Rootimport javax.net.ssl.SSLPeerUnverifiedException;
31d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Rootimport javax.net.ssl.SSLSession;
32d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Rootimport javax.net.ssl.SSLSessionContext;
33860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport javax.net.ssl.TrustManagerFactory;
34860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport javax.net.ssl.X509TrustManager;
35860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport junit.framework.TestCase;
36860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport libcore.java.security.TestKeyStore;
37860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
38860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootpublic class TrustManagerImplTest extends TestCase {
39860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
40860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private List<File> tmpFiles = new ArrayList<File>();
41860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
42860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private String getFingerprint(X509Certificate cert) throws Exception {
43860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        MessageDigest dgst = MessageDigest.getInstance("SHA512");
44860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        byte[] encoded = cert.getPublicKey().getEncoded();
45860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        byte[] fingerprint = dgst.digest(encoded);
46860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        return IntegralToString.bytesToHexString(fingerprint, false);
47860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
48860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
49860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private String writeTmpPinFile(String text) throws Exception {
50860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        File tmp = File.createTempFile("pins", null);
51860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        FileWriter fstream = new FileWriter(tmp);
52860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        fstream.write(text);
53860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        fstream.close();
54860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        tmpFiles.add(tmp);
55860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        return tmp.getPath();
56860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
57860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
58860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    @Override
59860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void tearDown() throws Exception {
60860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
61860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            for (File f : tmpFiles) {
62860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                f.delete();
63860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
64860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            tmpFiles.clear();
65860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } finally {
66860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            super.tearDown();
67860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
68860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
69860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
70860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    /**
71860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     * Ensure that our non-standard behavior of learning to trust new
72860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     * intermediate CAs does not regress. http://b/3404902
73860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     */
74860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void testLearnIntermediate() throws Exception {
75860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // chain3 should be server/intermediate/root
76860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        KeyStore.PrivateKeyEntry pke = TestKeyStore.getServer().getPrivateKey("RSA", "RSA");
77860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        X509Certificate[] chain3 = (X509Certificate[])pke.getCertificateChain();
78860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        X509Certificate root = chain3[2];
79860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        X509Certificate intermediate = chain3[1];
80860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        X509Certificate server = chain3[0];
81860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        X509Certificate[] chain2 =  new X509Certificate[] { server, intermediate };
82860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        X509Certificate[] chain1 =  new X509Certificate[] { server };
83860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
84860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // Normal behavior
85860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertValid(chain3,   trustManager(root));
86860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertValid(chain2,   trustManager(root));
87860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertInvalid(chain1, trustManager(root));
88860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertValid(chain3,   trustManager(intermediate));
89860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertValid(chain2,   trustManager(intermediate));
90860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertValid(chain1,   trustManager(intermediate));
91860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertValid(chain3,   trustManager(server));
92860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertValid(chain2,   trustManager(server));
93860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertValid(chain1,   trustManager(server));
94860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
95860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // non-standard behavior
96860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        X509TrustManager tm = trustManager(root);
97860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // fail on short chain with only root trusted
98860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertInvalid(chain1, tm);
99860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // succeed on longer chain, learn intermediate
100860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertValid(chain2, tm);
101860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // now we can validate the short chain
102860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertValid(chain1, tm);
103860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
104860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
105860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    // We should ignore duplicate cruft in the certificate chain
106860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    // See https://code.google.com/p/android/issues/detail?id=52295 http://b/8313312
107860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void testDuplicateInChain() throws Exception {
108860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // chain3 should be server/intermediate/root
109860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        KeyStore.PrivateKeyEntry pke = TestKeyStore.getServer().getPrivateKey("RSA", "RSA");
110860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        X509Certificate[] chain3 = (X509Certificate[])pke.getCertificateChain();
111860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        X509Certificate root = chain3[2];
112860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        X509Certificate intermediate = chain3[1];
113860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        X509Certificate server = chain3[0];
114860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
115860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        X509Certificate[] chain4 = new X509Certificate[] { server, intermediate,
116860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                                           server, intermediate
117860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
118860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertValid(chain4, trustManager(root));
119860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
120860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
121860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void testGetFullChain() throws Exception {
122860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // build the trust manager
123860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        KeyStore.PrivateKeyEntry pke = TestKeyStore.getServer().getPrivateKey("RSA", "RSA");
124860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        X509Certificate[] chain3 = (X509Certificate[])pke.getCertificateChain();
125860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        X509Certificate root = chain3[2];
126860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        X509TrustManager tm = trustManager(root);
127860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
128860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // build the chains we'll use for testing
129860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        X509Certificate intermediate = chain3[1];
130860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        X509Certificate server = chain3[0];
131860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        X509Certificate[] chain2 =  new X509Certificate[] { server, intermediate };
132860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        X509Certificate[] chain1 =  new X509Certificate[] { server };
133860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
134860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(tm instanceof TrustManagerImpl);
135860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        TrustManagerImpl tmi = (TrustManagerImpl) tm;
136d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        List<X509Certificate> certs = tmi.checkServerTrusted(chain2, "RSA", new MySSLSession(
137d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root                "purple.com"));
138860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals(Arrays.asList(chain3), certs);
139d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        certs = tmi.checkServerTrusted(chain1, "RSA", new MySSLSession("purple.com"));
140860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals(Arrays.asList(chain3), certs);
141860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
142860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
143860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void testCertPinning() throws Exception {
144860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // chain3 should be server/intermediate/root
145860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        KeyStore.PrivateKeyEntry pke = TestKeyStore.getServer().getPrivateKey("RSA", "RSA");
146860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        X509Certificate[] chain3 = (X509Certificate[]) pke.getCertificateChain();
147860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        X509Certificate root = chain3[2];
148860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        X509Certificate intermediate = chain3[1];
149860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        X509Certificate server = chain3[0];
150860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        X509Certificate[] chain2 =  new X509Certificate[] { server, intermediate };
151860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        X509Certificate[] chain1 =  new X509Certificate[] { server };
152860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
153860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // test without a hostname, expecting failure
154860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertInvalidPinned(chain1, trustManager(root, "gugle.com", root), null);
155860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // test without a hostname, expecting success
156860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertValidPinned(chain3, trustManager(root, "gugle.com", root), null, chain3);
157860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // test an unpinned hostname that should fail
158860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertInvalidPinned(chain1, trustManager(root, "gugle.com", root), "purple.com");
159860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // test an unpinned hostname that should succeed
160860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertValidPinned(chain3, trustManager(root, "gugle.com", root), "purple.com", chain3);
161860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // test a pinned hostname that should fail
162860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertInvalidPinned(chain1, trustManager(intermediate, "gugle.com", root), "gugle.com");
163860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // test a pinned hostname that should succeed
164860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertValidPinned(chain2, trustManager(intermediate, "gugle.com", server), "gugle.com",
165860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                                                                            chain2);
166860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
167860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
168860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private X509TrustManager trustManager(X509Certificate ca) throws Exception {
169860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        KeyStore keyStore = TestKeyStore.createKeyStore();
170860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        keyStore.setCertificateEntry("alias", ca);
171860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
172860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        String algorithm = TrustManagerFactory.getDefaultAlgorithm();
173860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
174860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        tmf.init(keyStore);
175860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        return (X509TrustManager) tmf.getTrustManagers()[0];
176860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
177860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
178860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private TrustManagerImpl trustManager(X509Certificate ca, String hostname, X509Certificate pin)
179860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                          throws Exception {
180860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // build the cert pin manager
181860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        CertPinManager cm = certManager(hostname, pin);
182860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // insert it into the trust manager
183860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        KeyStore keyStore = TestKeyStore.createKeyStore();
184860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        keyStore.setCertificateEntry("alias", ca);
185860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        return new TrustManagerImpl(keyStore, cm);
186860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
187860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
188860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private CertPinManager certManager(String hostname, X509Certificate pin) throws Exception {
189860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        String pinString = "";
190860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        if (pin != null) {
191860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            pinString = hostname + "=true|" + getFingerprint(pin);
192860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
193860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // write it to a pinfile
194860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        String path = writeTmpPinFile(pinString);
195860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // build the certpinmanager
196860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        return new CertPinManager(path, new TrustedCertificateStore());
197860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
198860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
199860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private void assertValid(X509Certificate[] chain, X509TrustManager tm) throws Exception {
200860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        if (tm instanceof TrustManagerImpl) {
201860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            TrustManagerImpl tmi = (TrustManagerImpl) tm;
202860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            tmi.checkServerTrusted(chain, "RSA");
203860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
204860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        tm.checkServerTrusted(chain, "RSA");
205860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
206860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
207860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private void assertValidPinned(X509Certificate[] chain, X509TrustManager tm, String hostname,
208860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                   X509Certificate[] fullChain) throws Exception {
209860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        if (tm instanceof TrustManagerImpl) {
210860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            TrustManagerImpl tmi = (TrustManagerImpl) tm;
211d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            List<X509Certificate> checkedChain = tmi.checkServerTrusted(chain, "RSA",
212d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root                    new MySSLSession(hostname));
213860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(checkedChain, Arrays.asList(fullChain));
214860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
215860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        tm.checkServerTrusted(chain, "RSA");
216860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
217860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
218860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private void assertInvalid(X509Certificate[] chain, X509TrustManager tm) {
219860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
220860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            tm.checkClientTrusted(chain, "RSA");
221860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
222860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (CertificateException expected) {
223860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
224860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
225860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            tm.checkServerTrusted(chain, "RSA");
226860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
227860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (CertificateException expected) {
228860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
229860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
230860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
231860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private void assertInvalidPinned(X509Certificate[] chain, X509TrustManager tm, String hostname)
232860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                     throws Exception {
233860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(tm.getClass().getName(), tm instanceof TrustManagerImpl);
234860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
235860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            TrustManagerImpl tmi = (TrustManagerImpl) tm;
236d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            tmi.checkServerTrusted(chain, "RSA", new MySSLSession(hostname));
237860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
238860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (CertificateException expected) {
239860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
240860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
241d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
242d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root    private class MySSLSession implements SSLSession {
243d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        private final String hostname;
244d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
245d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        public MySSLSession(String hostname) {
246d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            this.hostname = hostname;
247d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        }
248d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
249d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        @Override
250d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        public int getApplicationBufferSize() {
251d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            throw new UnsupportedOperationException();
252d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        }
253d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
254d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        @Override
255d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        public String getCipherSuite() {
256d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            throw new UnsupportedOperationException();
257d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        }
258d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
259d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        @Override
260d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        public long getCreationTime() {
261d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            throw new UnsupportedOperationException();
262d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        }
263d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
264d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        @Override
265d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        public byte[] getId() {
266d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            throw new UnsupportedOperationException();
267d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        }
268d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
269d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        @Override
270d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        public long getLastAccessedTime() {
271d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            throw new UnsupportedOperationException();
272d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        }
273d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
274d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        @Override
275d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        public Certificate[] getLocalCertificates() {
276d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            throw new UnsupportedOperationException();
277d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        }
278d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
279d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        @Override
280d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        public Principal getLocalPrincipal() {
281d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            throw new UnsupportedOperationException();
282d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        }
283d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
284d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        @Override
285d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        public int getPacketBufferSize() {
286d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            throw new UnsupportedOperationException();
287d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        }
288d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
289d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        @Override
290d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        public javax.security.cert.X509Certificate[] getPeerCertificateChain()
291d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root                throws SSLPeerUnverifiedException {
292d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            throw new UnsupportedOperationException();
293d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        }
294d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
295d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        @Override
296d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
297d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            throw new UnsupportedOperationException();
298d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        }
299d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
300d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        @Override
301d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        public String getPeerHost() {
302d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            return hostname;
303d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        }
304d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
305d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        @Override
306d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        public int getPeerPort() {
307d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            throw new UnsupportedOperationException();
308d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        }
309d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
310d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        @Override
311d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
312d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            throw new UnsupportedOperationException();
313d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        }
314d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
315d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        @Override
316d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        public String getProtocol() {
317d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            throw new UnsupportedOperationException();
318d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        }
319d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
320d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        @Override
321d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        public SSLSessionContext getSessionContext() {
322d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            throw new UnsupportedOperationException();
323d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        }
324d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
325d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        @Override
326d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        public Object getValue(String name) {
327d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            throw new UnsupportedOperationException();
328d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        }
329d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
330d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        @Override
331d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        public String[] getValueNames() {
332d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            throw new UnsupportedOperationException();
333d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        }
334d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
335d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        @Override
336d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        public void invalidate() {
337d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            throw new UnsupportedOperationException();
338d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        }
339d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
340d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        @Override
341d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        public boolean isValid() {
342d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            throw new UnsupportedOperationException();
343d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        }
344d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
345d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        @Override
346d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        public void putValue(String name, Object value) {
347d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            throw new UnsupportedOperationException();
348d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        }
349d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
350d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        @Override
351d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        public void removeValue(String name) {
352d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            throw new UnsupportedOperationException();
353d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        }
354d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root    }
355860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root}
356